Abbreviations and symbols. Variables and conditional statement

A condition variable can be used to implement the synchronization relationships mentioned above: start-start (CC), finish-start (FS), start-finish (SF), and finish-finish (FF). These relationships can exist between threads of the same or different processes. Listings 5.4 and 5.5 provide examples of implementations of FS and FF synchronization relationships. Each example defines two mutexes. One mutex is used to synchronize access to shared data, and the other is used to synchronize code execution.

// Listing 5.4. FS synchronization relationships between

// two threads

pthread_t ThreadA,ThreadB;

pthread_cond_t Event;

void * worker1(void *X) (

for(int Count = l;Count

pthread_mutex_lock(&Mutex);

pthread_mutex_unlock(&Mutex);

if(Number == 50)(

pthread_cond_signal(&Event);

void * worker2(void *X) (

pthread_mutex_lock(&EventMutex);

pthread_cond_wait(&Event,&EventMutex);

for(int Count = 1;Count

pthread_mutex_lock(&Mutex);

Number = Number + 20;

pthread_mutex_unlock(&Mutex);

cout ""Function worker2 has completed execution." "endl; return(0);

int main(int argc, char *argv) (

pthread_mutex_init(&Mutex,NULL);

pthread_mutex_init(&EventMutex,NULL);

pthread_cond_init(&Event, NULL);

pthread_create(&ThreadA, NULL, workerl, NULL);

pthread_create(&ThreadB, NULL, worker2, NULL);

Listing 5.4 shows an example implementation of FS synchronization relationships. ThreadA cannot terminate until ThreadB starts. If Number becomes 50, ThreadA signals this to ThreadB. It can now continue executing until the very end. ThreadB cannot begin executing until it receives a signal from ThreadA. ThreadB uses an EventMutex object along with an Event condition variable. A Mutex object is used to synchronize access to write the value of the Number shared variable. A task can use multiple mutexes to synchronize various events and access critical sections.

An example implementation of FF synchronization relationships is shown in Listing 5.5.

// Listing 5.5. FF synchronization relationship between // two threads

pthread_t ThreadA, ThreadB ;

pthread_mutex_t Mutex, EventMutex;

pthread_cond_t Event;

void *workerl(void *X) (

for(int Count = l;Count

pthread_mu tex_l ock (&Mutex);

pthread_mutex_unlock(&Mutex);

cout ""workerl: number is "

pthread_mutex_lock(&EventMutex) ,-

cout "The workerl function is waiting. " "endl;

pthread_cond_wait (&Event, &EventMutex) ;

pthread_mutex_unlock(&EventMutex);

void *worker2 (void *X) (

for(int Count = l;Count

pthread_mutex_lock(&Mutex) ;

Number = Number * 2 ;

pthread_mutex_unlock(&Mutex) ;

cout " "worker2: number is " " Number " endl;

pthread_cond_signal (&Event) ;

cout ""The worker2 function sent a signal" "endl;return(0);

int main(int argc, char *argv) (

pthread_mutex_init (&Mutex,NULL) ;

pthread_mutex_init (&EventMutex,NULL) ;

pthread_cond_init (&Event, NULL) ;

pthread_create(&ThreadA, NULL,workerl, NULL);

pthread_create (&ThreadB, NULL, worker2, NULL) ;

In Listing 5.5, ThreadA cannot terminate until ThreadB terminates. ThreadA must complete the loop 10 times, and ThreadB must complete the loop 100 times. ThreadA will complete its iterations before ThreadB, but will wait until ThreadB signals its completion.

CC and SF synchronization relationships cannot be implemented in this way. These methods are used to synchronize pores I execution time I processes.

TAU – theory of automatic control

TS – technical system

OU - control object

УУ - control device

CS – control system

Executive body - executive body

IU – actuator

D – sensor

OS - feedback

PC – transfer coefficient

TF – transfer function

AFC – amplitude-phase frequency response

Frequency response – amplitude-frequency response

LFC – logarithmic amplitude-frequency characteristic

PFC - phase-frequency response

2. Conventions of main variables and functions

x(t) – input signal of the control system element, output signal of the op-amp and control system (controlled quantity)

y(t) – output signal of the control system element, input signal of the op-amp (control action)

x z ( t) – setting influence of the control system

z(t) – disturbing influence on the control system

(t) – error (mismatch) signal in the control system

1(t) – single step impact

(t) – single impulse action

x m ,y m– amplitude values ​​of signals x(t) And y(t)

p – Laplace operator, differentiation operator

 - circular frequency, Fourier transform operator

X(p) – image of a continuous signal x(t) according to Laplace

X(j) – image of a continuous signal x(t) according to Fourier

k – link PC (or link connection)

W(p) – PF of a link (or connection of links)

W(j) – AFC of a link (or connection of links)

A() – frequency response of a link (or connection of links)

() – phase response of a link (or connection of links)

F( r) – PF of a closed control system

h(t) – transition function (characteristic) of a link or control system

w(t) – impulse (weight) function (characteristic) of a link or control system

INTRODUCTION

Automatic control theory (TAC)– a scientific discipline, the subject of study of which is information processes occurring in control systems of technical and technological objects. TAU identifies general patterns of functioning of automatic systems of various physical natures and, based on these patterns, develops principles for constructing high-quality control systems.

When studying control processes in TAU, they abstract from the physical and design features of systems and instead real systems consider their adequate mathematical models. The more accurately (more completely) the mathematical model corresponds to the physical processes occurring in the real system, the more perfect the designed control system will be.

The main research methods at TAU ​​are mathematical modeling, the theory of ordinary differential equations, operational calculus and harmonic analysis. Let's look briefly at each of them.

Mathematical modeling method, which combines a wide variety of methods and techniques for describing and representing physical objects and phenomena, can be conditionally, schematically represented using the most commonly used technique - a graphical representation of a simple object that has one input signal x(t) and one output signal y(t), in the form of a rectangle (Fig. B. 1, A). Symbol A inside a rectangle means some mathematical operator (function, integral, etc.) that connects input and output signals that vary over time.

Rice. B.1. Schematic representation of the mathematical methods used in TAU

Theory of ordinary differential equations, focusing its attention on the physical aspects and applications of the resulting solutions, serves as the main methodological basis of TAU, and ordinary differential equations themselves are the most general and complete form of mathematical description of elements and control systems. Differential equations relate time-varying input and output variables and their derivatives. In the simplest case, the differential equation has the form

dy(t)/dt=f[x(t),y(t)]. (B.1)

Operational calculus method, which is based on the Laplace transform

(B.2)

allows you to algebraize differential equations - go to the so-called operator equations connecting images X(p) And Y(p) input and output signals through the transfer function W(p) (Fig. B. 1, b)

W(p)=Y(p)/X(p). (B.3)

Harmonic analysis method based on the Fourier transform known from mathematics courses, which has the form

(B.4)

Using the Fourier transform (B. 4), images are found X(j) and Y(j) input and output signals x(t) And y(t), characterizing the frequency spectra of these signals. The Fourier images of the signals are connected (Fig. B. 1, V) frequency transfer function

W(j) =Y(j)/X(j). (B.5)

All four methods, briefly presented above, form the mathematical apparatus of TAU. On its basis, a set of “own” TAU methods has been developed, which are presented in this course.

TAU, together with the theory of construction and operation of control system elements (sensors, regulators, actuators) forms a broader branch of science - automation. Automation, in turn, is one of the branches of technical cybernetics. Technical cybernetics studies complex automated control systems for technological processes (APCS) and enterprises (APCS), built using control computers (CCM).

Technical cybernetics, along with biological and socioeconomic ones, is an integral part of cybernetics, which its founder, the American mathematician N. Wiener, defined in 1948 as the science of control and communications in technical systems and living organisms.

The first industrial regulators appeared in the period 1765-1804. (I. Polzunov, J. Watt, J. Jacquard).

The first theoretical studies of regulators appeared in the period 1868-1893. (J. Maxwell, I. Vyshnegradsky, A. Stodola). Russian scientist and engineer I. A. Vyshnegradsky performed a number of scientific research, in which the steam engine and its regulator were first analyzed by mathematical methods as a single dynamic system. The works of A. A. Andronov, V. S. Kulebakin, I. N. Voznesensky, B. V. Bulgakov, A. A. Feldbaum, B. N. Petrov, N. N. Krasovsky played a major role in the formation of the Russian TAU school , A. A. Voronova, Y. Z. Tsypkina, V. S. Pugacheva, ...

The development of modern control theory from the so-called “classical” control theory, based on the above-mentioned four main methods of TAU research, and the formation of its newest methods are schematically illustrated in Fig. V. 2.

Rice. B.2. Development of the content and methodology of management theory

Currently, TAU, along with the newest sections general management theory (operations research, systems engineering, game theory, queuing theory) plays a vital role in improving and automating the management of technological processes and production.

Conditional Variables

A condition variable (condvar is short for condition variable) is used to block a thread based on some condition while executing a critical section of code. The condition can be as complex as desired and does not depend on the condition variable. However, a condition variable must always be used in conjunction with a mutex to test a condition.

Conditional variables support following functions:

· waiting for a conditional variable (wait) ( pthread_cond_wait());

· single stream unblocking (signal) ( pthread_cond_signal())

· multiple stream unblocking (broadcast) ( pthread_cond_broadcast()),

Let's give an example typical use conditional variable:

pthread_mutex_lock (&m) ;-…

while (!arbitrary condition) (

pthread_cond_wait(&cv, &m);

pthread_mutex_unlock (&m) ;

In this example, the mutex is acquired before the condition is checked. This way, the condition being tested applies only to the current thread. Bye this condition is true, this section of code blocks on the wait call until some other thread performs a single or multiple thread unblock operation on the condition variable.

while loop in the example above it is required for two reasons. Firstly, posix standards do not guarantee the absence of false awakenings (for example, in multiprocessor systems). Second, if another thread changes a condition, it must be re-checked to ensure that the change meets the accepted criteria. When a waiting thread is blocked, the mutex associated with the condition variable is atomically released by the function pthread_cond_wait() so that another thread can enter a critical section of the program code.

A thread that performs a single thread unblock unblocks the thread with highest priority, which is queued on the condition variable. The multiple thread unblocking operation unblocks all threads queued on the condition variable. The mutex associated with the condition variable is released atomically by the thread with the highest priority that is unblocked. After processing the critical section of code, this thread must release the mutex.

Another type of conditional variable wait operation ( pthread__cond_timedwair()) allows you to set a timeout. At the end of this period, the waiting thread can be unblocked.

Barriers

A barrier is a synchronization mechanism that allows you to coordinate the work of several interacting threads so that each of them stops at given point waiting for the remaining threads before continuing its work.

Unlike the function pthreadjoin(), in which a thread waits for another thread to complete, the barrier forces the threads meet V certain point. Once the specified number of threads reaches the configured barrier, All these threads will be unblocked and continue their work. The barrier is created using the function pthread_barrier_init():

#include

pthread_barrier_init (pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count);

This code creates a barrier at the given address (the pointer to the barrier is in the barrier argument) and with the attributes set by the attr argument. The count argument specifies the number of threads that should call pthread_barrier_wait().

After creating the barrier, each thread calls the pthread_barrier_wait() function, thereby signaling the completion of this action:

#include

int pthread_barrier_wait(pthread_barrier_t "barrier);

When a thread calls a function pthread_barrier_wait(), it blocks until the number of threads specified by the function pthread_barrier_init(), will not call the function pthread_jbarrier_wait() and, accordingly, will not be blocked. After the specified number of threads have called the function pthread_barrier_wait(), they are all unlocked simultaneously.

#include

#include

#include

#include

pthread_barrier_t barrier; // synchronization object of the "barrier" type

main() // ignore arguments

time_t now;// create a barrier with counter value 3

pthread_barrier_init(&barrier, NULL, 3); // start two threads - threadl and thread2

pthread_create(NOLL, NOLL, threadl, NULL); // threads threadl and thread2 are running

pthread_create(NDLL, NDLL, thread2, NDLL);//wait for completion

printf("main() waiting for barrier at %s", ctime (&now));

pthread_barrier_wait (&barrier); // after this point all three threads are terminated

printf ("barrier in mainO done at %s", ctime (&now));

threadl (void *not used)

time(&now); // perform calculations

printf ("threadl starting at %s", ctime (&now)); // pause

pthread_barrier_wait (&barrier) ;// after this point all three threads are terminated

printf ("barrier in threadl() done at %s", ctime (&now)) ;

thread2 (void *not__used)

time(&now); // perform calculations

printf ("thread2 starting at %s", ctime (&now)); // pause

pthread_barrier_wait (&barrier) ;

// after this point all three threads are completed

printf ("barrier in thread2() done at %s", ctime (&now));

In the example from the listing, the main thread creates a barrier, after which it starts counting the number of threads blocked on the barrier for synchronization. IN in this case the number of synchronized threads is set to 3: thread main(), thread thread1() and thread thread2().

Threads thread1() and thread2() are launched. For clarity, a pause is set in the flow to simulate the computation process. To perform synchronization, the main thread is blocked on a barrier and waits for an unlock, which will occur after the other two threads do not join it at that barrier.



Waiting for blocking

Sleepon locks work similarly to condition variables, with a few exceptions. As are conditional variables waiting for a lock ( pthread_sleepon_lock()) can be used to block a thread until a condition becomes true (similar to changing the value of a memory location). But unlike condition variables (which must exist for every condition being tested), wait locks apply to a single mm.tex and dynamically created condition variable, regardless of the number of conditions being tested. The maximum number of conditional variables ends up being maximum number blocked threads.

Conditional Variables

Conditional variable is a semaphore used to signal an event that has occurred. One or more processes (or threads) may be waiting for a signal that some event has occurred from other processes or threads. You should understand the difference between condition variables and the mutex semaphores discussed above. The purpose of a mutex semaphore and read-write locks is to synchronize access to data, while condition variables are typically used to synchronize a sequence of operations. On this subject in his book UNIX Network Programming W. Richard Stevens said it well: “ Mutexes should be used for blocking, not waiting ».

In Listing 4.6, the consumer thread contained a loop:

15 while(TextFiles.empty())

The consumer thread iterated the loop until it was in the queue TextFiles there were elements. This loop can be replaced by a conditional loop m ennaya. The producer thread notifies the consumer that elements have been placed in the queue. The consumer thread can wait until it receives a signal and then proceed to process the queue.

The condition variable is of type pthread_cond_t. The following are the types of operations it can perform:

Initialization;

Destruction;

Expectation;

Waiting with time limit;

Addressable alarm;

Universal alarm;

Initialization and destruction operations are performed by condition variables, similar to similar operations of other mutexes. Class functions pthread_cond_t, which implement these operations are listed in table. 5.7.

Table 5.7. Functions of the pthread_cond_t class that implement conditional variable operations

Condition variables are used in conjunction with mutexes. If you try to lock a mutex, the thread or process will be blocked until the mutex is released. Once unblocked, the thread or process will receive a mutex and continue its work. When using a condition variable, it must be associated with a mutex.

pthread_mutex_lock(&Mutex) ;

pthread_cond_wait(&EventMutex, &Mutex);

pthread_mutex_unlock(&Mutex) ;

So, some task is trying to lock a mutex. If the mutex is already locked, then this task is blocked. After unlocking the task will release the mutex Mutex and at the same time will wait for a signal for the conditional variable EventMutex . If the mutex is not locked, the task will wait for a signal indefinitely. With a timed wait, the task will wait for a signal for a specified amount of time. If this time expires before the task receives a signal, the function will return an error code. The task will then request the mutex again.

By performing address signaling, a task notifies another thread or process that some event has occurred. If a task is waiting for a signal for a given condition variable, that task will be unblocked and receive a mutex. If several tasks are waiting for a signal for a given conditional variable at once, then only one of them will be unlocked. The remaining tasks will wait in the queue and will be released according to the scheduling strategy used. When a global signaling operation is performed, all tasks waiting for a signal for the specified condition variable will be notified. When multiple tasks are unlocked, they will compete for ownership of the mutex according to the scheduling strategy used. Unlike a wait operation, a task that performs a signaling operation does not claim ownership of the mutex, although it should.

The conditional variable also has an attribute object, the functions of which are listed in table. 5.8.

Table 5.8. Functions for accessing an attribute object for a condition variable of type pthread_cond_t


Int pthread_condattr_init(pthread_condattr_t * attr) Initializes the condition variable attribute object specified by attr to the default values ​​for all implementation-defined attributes;

Int pthread_condattr_destroy(pthread_condattr_t * attr) ; Destroys the condition variable attribute object specified by the attr parameter. This object can be reinitialized by calling pthread_condattr_init()

Int pthread_condattr_setpshared(pthread_condattr_t * attr,int pshared);

Int pthread_condattr_getpshared(const pthread_condattr_t * restrict attr, int *restrict pshared); Sets or returns the process-shared attribute of a condition variable attribute object, specified by parameter attr. The pshared parameter can contain the following values:

PTHREAD_PROCESS_SHARED(allows a read-write lock to be shared by any threads that have access to the memory allocated to this condition variable, even if the threads belong to different processes);

PTHREAD_PROCESS_PRIVATE(The Condition Variable is shared between threads of the same process)

Int pthread_condattr_setclock(pthread_condattr_t * attr, clockid_t clock_id);

Int pthread_condattr_getclock(const pthread_condattr_t * restrict attr, clockid_t * restrict clock_id); Sets or returns an attribute clock attribute object of a conditional variable specified by the parameter attr. Attribute clock represents the identifier of the clock used to measure the time limit in the pthread_cond_timedwait() function. The clock attribute defaults to the system clock identifier

Announcement

Variable is a quantity that has a name and meaning. Variables are declared using the word var: var x = 12, y; Here two variables are entered with the names x and y, the value 12 is written to the variable x, and the variable y is not defined, that is, the trace command trace (y); will produce the result undefined (the value is not defined). The trace (z) command produces the same result; because the variable z is generally unknown. In order to distinguish an existing variable from an unknown one, you can write a special zero value into it null value: var y = null ;

If the type of a variable is not explicitly specified, it can take any value. For example:

var x = 1; // number x = "Ku-ku!" ; // line x = false ; // boolean value

However, when declaring it, it is better to explicitly indicate the type of the variable. This allows many errors to be detected before the program is executed. There are three simple types:

  • Number number;
  • String string;
  • Boolean boolean value.
The type of a variable is indicated after its name, separated by a colon var x:Number = 0, y:String = "qq" , b:Boolean = false ; IN type variables String can be written as character strings enclosed in quotes or single apostrophes: var s1:String = "qq1", s2:String = "qq2"; Boolean variables take only two values: true and false: var b:Boolean = false ; b = true ; b = (a B the latter case the value of the variable b will be true if the condition to the right of the equal sign is true.

If you try to write a value of the wrong type to a variable, you will receive an error message immediately when translating the program (that is, when translating it into machine codes), and not at runtime. For example, this code causes an error:

var x:Number = 1; x = "Peek-a-boo!" ;

Variable Visibility

There are three types of variables: Global variables are declared using the _global descriptor: _global .x = 12; Note that the word var does not need to be used here; such variables are treated as properties of the _global object. The x variable, which is declared above, can be accessed from any function and from the code of any clip simply by name.

If there are multiple variables with the same name in scope, the local variable is looked up first, then the current clip variable, and then the global variable.

Variables of other clips are “not visible”; to access them you need to explicitly specify the parent clip:

Mc.x = 1; _root.x = 12; _parent.x = 123;

Assignment

To assign a new value to a variable, use the = sign. To the left of it is written the name of the variable, and to the right the expression: a = 4*(c + 2) + 3 / (r - 4*w) + d % 3; The * sign means multiplication, the / sign means division, and the % sign means taking the remainder of the division.

In an expression, arithmetic operations are performed in the following order:

  • actions in brackets;
  • multiplication, division and remainder (from left to right);
  • addition and subtraction (from left to right).
This order is called priority(seniority) arithmetic operations.

Character strings can be concatenated using the + operator:

No = 20; s = "Vasya" + "went for a walk." ; qq = "Object" + no; If the expression involves data of different types, automatic conversion to one type occurs. So in the last line the string Object20 is written to the variable qq.

Very often programs use the operators ++ ( increment, increase the variable by 1, and -- ( decrement, decreasing the variable by 1). Operators

I++; k --; mean the same as i = i + 1; k = k - 1; There is also a shorthand notation for arithmetic operations: a += 20; b -= c - d; c *= a + b; d /= 2*c; f %= 12; This code can be replaced with the following operators in “normal” form: a = a + 20; b = b - (c - d); c = c * (a + b); d = d / (2 * c); f = f % 12

Objects

An object is something that has properties and methods. In the environment Flash There are built-in objects (eg Array, MovieClip, Key). In addition, you can build your own objects: var car = new Object (); car.v = 10; car.year = 1998; In the environment Flash you can use object-oriented programming, that is, create your own classes of objects, endow them with properties and methods (see Topic 13).

The main feature of objects is the so-called reference addressing. That is, when announcing

var obj = new Object(); the obj variable does not store the object itself, but only it address(link to object). Therefore, the assignment operator obj2 = obj; does not create in memory new object, which is a copy of the object obj , but simply copies the address of the first object into the variable obj2 . After this, obj and obj2 point to the same object. If we want to actually build a copy of the object whose address is stored in obj , we can do this: var obj2 = new Object(); for (prop in obj) obj2 = obj; Here, in a loop, all the properties of the first object are sorted out and copied to the second. Variable prop ( character string) this is the name of the next property. The entry obj means " property of the obj object whose name is stored in prop».