Diseases, endocrinologists. MRI
Site search

Panic disorders. What actions committed while drunk are you very ashamed of? Processing one-time tasks


02.10.2011, 21:27

For beating up a guy and hanging his T-shirt on a tree. And she chased the idiot guy alone for a couple of kilometers and when he fell she started peeing on him. But they deserved it.

I'm in big company I pestered a girl and said that her boyfriend bought it at a sale and also ate bananas and laid the peels on everyone’s laps in the marshmallow, and I also constantly organize lesbian shows in bars, once I looked under the skirts of waitresses in a VIP club and gave out comments, but in general I’m a bad drunk and I immediately forget that I love people saying if you wake up and you are ashamed but don’t remember why exactly about me

After the last drunkenness I'm fed up:
1. screamed from the balcony to the guy “suck me”
2. ate a cigarette
3. threw apples
4. called the guy and told him that I won’t give him sex in a rude manner
5. drowned bulls in grapefruit juice
6. called my mom and told me that I was sober
7. I asked my friend’s boyfriend to bring us some wine.
8. I peed past the toilet, since there were 2 of them - I chose the wrong one, and then fell
9. fell out of the bath

I ran around the apartment with a knife after my husband once, although I drank a couple of glasses of champagne. The next morning I became scared - what if I hit him with a knife, but I just decided to scare him. And I don’t know why I got such a kick!

It’s always the same thing, like when I get drunk I go to the park to look for wankers to make fun of them, or I create these topics on the forum... in the morning I think, am I stupid?...

Once a guy was hitting on me, and I was so drunk that I started explaining to him popularly that nothing would go wrong, because I was “Bloody Mary” (they were) and this nickname sank into my soul so much that I almost I shouted to everyone I met: “I am Bloody Mary,” fortunately it was not in my hometown

-* called my ex, expressed everything I thought about him
*called my beloved, said how much I want him
*ate shawarma with foil
* swore at a guy I met at a club, although he helped me and brought me water
*danced a striptease in a club in a competition, received second place
*threw ice at a stranger
*my man’s friend drives a yellow Hummer. I have never seen anything like this in Korea. when we all went to party together. I leaned out of my man’s car, and, pointing to the Hummer driving ahead, I yelled that this car was my friend
*yesterday I was at the club. when I was driving home in a taxi in the morning, I told the driver: [translation from Korean. verbatim!] “The food I ate just told me it wants to come out!”
*I also have a Mongolian friend. I climbed onto his back, forced him to carry me on his back and shouted to the whole street that he was my Mongolian horse
but in general there was a lot more, you won’t remember...

I wrote to the guy at 4 o’clock in the morning “ Good night, Expensive"

My friends and I got drunk on cognac, everyone went home, and I stupidly called a taxi (it was 3 a.m.) and went to ex-boyfriend with whom I broke up 4 months ago (we remained friends). I don’t remember how I got into the entrance, got to his apartment, started banging on his door and yelling “MARRY ME MARAT”, he poor thing went crazy. He dragged me home and into a cold shower, gave me strong tea. After two hours, I left, and then when I realized what I had done, I WAS INCREDIBLY ASHAMED. After that, we made up and are still together. After that I don’t drink another glass of champagne.


...

02.10.2011, 22:09

The murdered woman was walking with a guy through the garden, and then it seemed to me that he had somehow offended me by walking a few steps ahead of me, and not next to me. I got offended and climbed a tree, but he didn’t even notice... he ran around the garden for an hour and a half looking for me... and I calmly passed out on the tree and slept until the morning. ...
...
But in the morning I couldn’t immediately remember how I ended up on the branches. Holy shit how it was after
;D;D;D

Interpretation

02.10.2011, 22:42

I am ashamed of certain actions committed while sober :) But this is closer to philosophy. While drunk... a lot of things were fun, embarrassing... no, sorry)))))

Elena Lotus

02.10.2011, 23:17

Yesterday, after I realized that my phone (OOO!!!) is no longer mine, I got drunk. heavily. and (who knows me, don’t say that I drink like a mouse) then I did something... that only to close friends, by and large secret and then I’ll think about who I can tell... The Paberti restaurant was shocked again. Now I’m looking at the photo gallery in the hope of seeing what happened: (but I’m not ashamed... no... I just thought that I was decent.

02.10.2011, 23:31

;D;D;D
I have always maintained that aunties should not drink!!! EVERYONE!!!;)

..;D;D;D you speak the truth

02.10.2011, 23:36

A drunk woman is like a Chinese down jacket: soft and fits.
Galygin

Elena Lotus

02.10.2011, 23:41

But men like yes? Everyone can drink. and aunts and uncles...you just need to be careful...today your head doesn’t hurt...your soul hurts...will you get a drink? It’s just a vicious circle;)

03.10.2011, 00:15

Drink anything and everything while you are young and healthy :)

03.10.2011, 01:48

selectively stolen from the women's forum :)

I almost peed in the laundry basket in front of my mother..... confused with the toilet.... oops....

The murdered woman was walking with a guy through the garden, and then it seemed to me that he had somehow offended me by walking a few steps ahead of me, and not next to me. I got offended and climbed a tree, but he didn’t even notice... he ran around the garden for an hour and a half looking for me... and I calmly passed out on the tree and slept until the morning. ...
...
But in the morning I couldn’t immediately remember how I ended up on the branches. Holy shit how it was after

On the balcony there were basins and pots where my mother grew onions. I “weakly” pissed in each of these pots =((((in my own beds ((of course I won’t tell my mom, throw everything the fuck in the trash, I’m here I decided to piss on your greens! Well, it continued to grow, then it went into the salad

03.10.2011, 05:35

My friends and I got drunk on cognac, everyone went home, and I stupidly called a taxi (it was 3 a.m.) and went to see my ex-boyfriend with whom I broke up 4 months ago (we remained friends). I don’t remember how I got into the entrance, got to his apartment, became to break down his door and yell “MARRY ME MARAT”, he, poor thing, went crazy. He dragged me home and into a cold shower, gave me strong tea. After two hours I left, and then when I realized what I had done, I WAS REALLY SHAMED. After that we They reconciled and are still together. After that I don’t drink another glass of champagne.

That's quite real story love.
And about the benefits of drinking too.

(Drink, girls, and happiness will come to you.)

HEART NEUROSIS (CARDIOPHOBIA). A special form of phobia, along with panic syndrome, is cardiophobia, which should be described especially due to its characteristic clinical picture and significant frequency. It mainly occurs in young people, more often in men, and also in children.

Paroxysmal anxiety states, in which patients fear that the heart will stop beating and death may occur, can occur without the presence of somatic disease. At the beginning of the next attack, nausea, dizziness, internal anxiety, and slight compression of the heart appear.

However, in many cases, without any warning, a severe attack occurs: palpitations felt throughout the body, some increase blood pressure, a heavy feeling of compression and tightness in the heart area, lack of air, sweating, dizziness and a feeling of fainting (but not loss of consciousness), trembling throughout the body and basic fear. The patient believes that his heart will stop in a second and he will drop dead. This is the fear of self-destruction and death. When very excited, patients run around and beg for help. If an attack of fear occurs while traveling in a car, the patient is forced to stop and take a break.

After the first attack, phobic development occurs. Patients lose their mental balance, live in constant fear, expecting the next attack or death, experiencing fear of fear (fear of anticipation, phobia). At the same time, they are not helped by the therapist’s message about normal indicators heart function, nor persuasion that previous attacks had no consequences. The frequency of attacks and the intervals between them are irregular. At intervals, the patient cautiously monitors his cardiac functions, controls the pulse and records its slightest deviations. He perceives random extrasystoles as indisputable signs of a disease with a hopeless outcome.

Patients observe with caution other vegetative manifestations, as well as slight fluctuations in their well-being. Patients take care of themselves, hardly dare to walk, strive to eliminate all stress, worries and, first of all, difficult situations in order to prevent an attack (evasive behavior). Instead of the fear of death, in many cases the fear of fear and of fear-inducing situations increasingly appears.

CONDITIONS OF APPEARANCE. The reason for the first cardiophobic attack is often an acute conflict and overstrain, separation and disappointment, a situation of loneliness and abandonment, as well as anxiety in the event of the cardiac death of someone close.

Knowing that cardiac death can always happen, even in the young and healthy, becomes a worrying factor. Intensive consumption of coffee and nicotine can trigger this process. The beginning often comes from childhood. Mostly spoiled and dependent children are affected, with a pronounced dependence on the mother, largely with ambivalent attitudes: the expectation of love, on the one hand, and the desire for independence with aggressive impulses, on the other, with contradictory fantasies of attachment and separation. Such attitudes are especially dangerous when connections are broken, separations and disappointments occur. A cardiophobe often lives in fear of separation before he realizes that he wants it and is afraid of it. Joint problems with parents and conflicts with partners regularly arise.

TREATMENT
If in acute condition the presence of a doctor and a conversation with him do not cause improvement; tranquilizers or beta blockers are indicated. Like other patients with neuroses with fear, many phobics try to self-medicate with alcohol; but its effect is insufficient, and the danger of becoming dependent on alcohol is great. Pharmacotherapy is only an auxiliary remedy, primarily in acute cases, as well as an initial effective remedy.

Psychotherapy is decisive. The sooner it starts, the better. Studying the causes and conflict situations immediately after the first cardiophobic attacks can stop subsequent phobic development. Later treatment more difficult to carry out and requires long-term psychotherapy.

With these and others anxiety disorders especially shown behavioral therapy(stimulating confrontation, cognitive therapy, self-confidence training). A distinctive feature of anxiety avoidance training is that it works on a desensitization model (to the corresponding conditions of everyday situations), and anxiety management training uses forced immersion in a phobic situation (flood) and the formation of coping strategies. For severe anxiety disorders, it is necessary to carry out clinical treatment using various models of psychotherapy.

It seems that PHP developers rarely use concurrency. I won’t talk about the simplicity of synchronous code; single-threaded programming is, of course, simpler and clearer, but sometimes a little use of parallelism can bring a noticeable increase in performance.

In this article, we'll take a look at how multithreading can be achieved in PHP using the pthreads extension. This will require the ZTS (Zend Thread Safety) version of PHP 7.x installed, along with the pthreads v3 extension installed. (At the time of writing, in PHP 7.1, users will need to install from the master branch in the pthreads repository - see third party extension.)

A small clarification: pthreads v2 is intended for PHP 5.x and is no longer supported, pthreads v3 is for PHP 7.x and is actively being developed.

After such a digression, let's get straight to the point!

Processing one-time tasks

Sometimes you want to process one-time tasks in a multi-threaded way (for example, performing a certain task related to I/O). In such cases, you can use the Thread class to create a new thread and run some processing on a separate thread.

For example:

$task = new class extends Thread ( private $response; public function run() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+)~", $content, $matches); $this->response = $matches; ) ); $task->start() && $task->join(); var_dump($task->response); // string (6) "Google"

Here the run method is our processing, which will be executed inside a new thread. When Thread::start is called, a new thread is spawned and the run method is called. We then join the child thread back to the main thread by calling Thread::join , which will block until the child thread has finished executing. This ensures that the task finishes executing before we try to print the result (which is stored in $task->response).

It may not be desirable to pollute a class with additional responsibilities associated with flow logic (including the responsibility of defining a run method). We can distinguish such classes by inheriting them from the Threaded class. Then they can be run inside another thread:

Class Task extends Threaded ( public $response; public function someWork() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ this->response = $matches; ) ) $task = new Task; $thread = new class($task) extends Thread ( private $task; public function __construct(Threaded $task) ( $this->task = $task; ) public function run() ( $this->task->someWork( ); ) ); $thread->start() && $thread->join(); var_dump($task->response);

Any class that needs to be run in a separate thread must inherit from the Threaded class. This is because it provides the necessary capabilities to perform processing on different threads, as well as implicit security and useful interfaces (such as resource synchronization).

Let's take a look at the class hierarchy offered by the pthreads extension:

Threaded (implements Traversable, Collectable) Thread Worker Volatile Pool

We've already covered and learned the basics of the Thread and Threaded classes, now let's take a look at the other three (Worker, Volatile, and Pool).

Reusing Threads

Starting a new thread for each task that needs to be parallelized is quite expensive. This is because a common-nothing architecture must be implemented in pthreads to achieve multithreading within PHP. Which means that the entire execution context of the current instance of the PHP interpreter (including every class, interface, trait, and function) must be copied for each thread created. Because this has a noticeable performance impact, the stream should always be reused whenever possible. Threads can be reused in two ways: using Workers or using Pools.

The Worker class is used to perform a number of tasks synchronously within another thread. This is done by creating a new Worker instance (which creates a new thread), and then pushing tasks onto that separate thread's stack (using Worker::stack).

Here's a small example:

Class Task extends Threaded ( private $value; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n"; ) ) $worker = new Worker(); $worker->start(); for ($i = 0; $i stack(new Task($i)); ) while ($worker->collect()); $worker->shutdown();

In the example above, 15 tasks for a new $worker object are pushed onto the stack via the Worker::stack method, and then they are processed in the order they were pushed. The Worker::collect method, as shown above, is used to clean up tasks as soon as they finish executing. With it, inside a while loop, we block the main thread until all tasks on the stack are completed and cleared - before we call Worker::shutdown . Terminating a worker early (i.e. while there are still tasks that need to be completed) will still block the main thread until all tasks have completed their execution, just that the tasks will not be garbage collected (which entails represent memory leaks).

The Worker class provides several other methods related to its task stack, including Worker::unstack for removing the last stacked task and Worker::getStacked for getting the number of tasks in the execution stack. A worker's stack contains only the tasks that need to be executed. Once a task on the stack has been completed, it is removed and placed on a separate (internal) stack for garbage collection (using the Worker::collect method).

Another way to reuse a thread across multiple tasks is to use a thread pool (via the Pool class). A thread pool uses a group of Workers to enable tasks to be executed simultaneously, in which the concurrency factor (the number of pool threads it operates with) is set when the pool is created.

Let's adapt the above example to use a pool of workers:

Class Task extends Threaded ( private $value; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Task: ($this->value) \n"; ) ) $pool = new Pool(4); for ($i = 0; $i submit(new Task($i)); ) while ($pool->collect()); $pool->shutdown();

There are a few notable differences when using a pool as opposed to a worker. First, the pool does not need to be started manually; it starts executing tasks as soon as they become available. Secondly, we send tasks to the pool, not put them on a stack. Additionally, the Pool class does not inherit from Threaded and therefore cannot be passed to other threads (unlike Worker).

It is a good practice for workers and pools to always clean up their tasks as soon as they have completed, and then manually terminate them themselves. Threads created using the Thread class must also be attached to the parent thread.

pthreads and (im)mutability

The last class we'll touch on is Volatile, a new addition to pthreads v3. Immutability has become an important concept in pthreads because without it, performance suffers significantly. Therefore, by default, properties of Threaded classes that are themselves Threaded objects are now immutable, and therefore they cannot be overwritten after their initial assignment. Explicit mutability for such properties is currently preferred, and can still be achieved using the new Volatile class.

Let's look at an example that will demonstrate the new immutability restrictions:

Class Task extends Threaded // a Threaded class ( public function __construct() ( $this->data = new Threaded(); // $this->data is not overwritable, since it is a Threaded property of a Threaded class ) ) $task = new class(new Task()) extends Thread ( // a Threaded class, since Thread extends Threaded public function __construct($tm) ( $this->threadedMember = $tm; var_dump($this->threadedMember-> data); // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); // invalid, since the property is a Threaded member of a Threaded class ) );

Threaded properties of Volatile classes, on the other hand, are mutable:

Class Task extends Volatile ( public function __construct() ( $this->data = new Threaded(); $this->data = new StdClass(); // valid, since we are in a volatile class ) ) $task = new class(new Task()) extends Thread ( public function __construct($vm) ( $this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // still invalid, since Volatile extends Threaded, so the property is still a Threaded member of a Threaded class $this->volatileMember = new StdClass(); ) );

We can see that the Volatile class overrides the immutability imposed by the parent Threaded class to provide the ability to change Threaded properties (as well as unset()).

There is another subject of discussion to cover the topic of variability and the Volatile class - arrays. In pthreads, arrays are automatically cast to Volatile objects when assigned to a property of the Threaded class. This is because it is simply not safe to manipulate an array of multiple PHP contexts.

Let's look at an example again to understand some things better:

$array = ; $task = new class($array) extends Thread ( private $data; public function __construct(array $array) ( $this->data = $array; ) public function run() ( $this->data = 4; $ this->data = 5; print_r($this->data); ) ); $task->start() && $task->join(); /* Output: Volatile Object ( => 1 => 2 => 3 => 4 => 5) */

We see that Volatile objects can be treated as if they were arrays because they support array operations such as (as shown above) the subset() operator. However, Volatile classes do not support basic array functions such as array_pop and array_shift. Instead, the Threaded class provides us with such operations as built-in methods.

As a demonstration:

$data = new class extends Volatile ( public $a = 1; public $b = 2; public $c = 3; ); var_dump($data); var_dump($data->pop()); var_dump($data->shift()); var_dump($data); /* Output: object(class@anonymous)#1 (3) ( ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3) ) int(3) int(1) object(class@anonymous)#1 (1) ( ["b"]=> int(2) ) */

Other supported operations include Threaded::chunk and Threaded::merge .

Synchronization

In the last section of this article, we will look at synchronization in pthreads. Synchronization is a method that allows you to control access to shared resources.

For example, let's implement a simple counter:

$counter = new class extends Thread ( public $i = 0; public function run() ( for ($i = 0; $i i; ) ) ); $counter->start(); for ($i = 0; $i i; ) $counter->join(); var_dump($counter->i); // will print a number from 10 to 20

Without the use of synchronization, the output is not deterministic. Multiple threads write to the same variable without controlled access, which means updates will be lost.

Let's fix this so that we get the correct output of 20 by adding timing:

$counter = new class extends Thread ( public $i = 0; public function run() ( $this->synchronized(function () ( for ($i = 0; $i i; ) )); ) ); $counter->start(); $counter->synchronized(function ($counter) ( for ($i = 0; $i i; ) ), $counter); $counter->join(); var_dump($counter->i); // int(20)

Synchronized code blocks can also communicate with each other using the Threaded::wait and Threaded::notify (or Threaded::notifyAll) methods.

Here is an alternate increment in two synchronized while loops:

$counter = new class extends Thread ( public $cond = 1; public function run() ( $this->synchronized(function () ( for ($i = 0; $i notify(); if ($this->cond === 1) ( $this->cond = 2; $this->wait(); ) ) )); ) ); $counter->start(); $counter->synchronized(function ($counter) ( if ($counter->cond !== 2) ( $counter->wait(); // wait for the other to start first ) for ($i = 10; $i notify(); if ($counter->cond === 2) ( $counter->cond = 1; $counter->wait(); ) ) ), $counter); $counter->join(); /* Output: int(0) int(10) int(1) int(11) int(2) int(12) int(3) int(13) int(4) int(14) int(5) int( 15) int(6) int(16) int(7) int(17) int(8) int(18) int(9) int(19) */

You may notice additional conditions, which were placed around the call to Threaded::wait . These conditions are critical because they allow the synchronized callback to resume when it has received a notification and the specified condition is true . This is important because notifications can come from places other than when Threaded::notify is called. Thus, if calls to the Threaded::wait method were not enclosed in conditions, we will execute false wake up calls, which will lead to unpredictable code behavior.

Conclusion

We looked at the five classes of the pthreads package (Threaded, Thread, Worker, Volatile, and Pool) and how each class is used. We also looked at the new concept of immutability in pthreads, made short review supported synchronization capabilities. With these basics in place, we can now begin to look at the use of pthreads in cases such as real world! This will be the topic of our next post.

If you are interested in the translation of the next post, let me know: comment on social media. networks, upvote and share the post with colleagues and friends.

There are quite a few solutions floating around the web for emulating multithreading in PHP. Most often they are based on forks, but there are also variations on the theme using curl, proc_open and so on.

All the options I came across did not suit me for one reason or another, and I had to write my own solution. I had the following set of requirements:

  • Use of forks;
  • Synchronous mode with preservation of the interface in the absence of the necessary extensions;
  • Reuse of child processes;
  • Full data exchange between processes. Those. run with arguments and get the result when finished;
  • The ability to exchange events between a child “thread” process and the main process during operation;
  • Working with a thread pool while maintaining reuse, passing arguments, and getting results;
  • Handling runtime errors;
  • Timeouts for performing work, waiting for work by a thread, initialization;
  • Maximum performance.

The result was the AzaThread library (formerly CThread).

Description

AzaThread provides a simple interface for creating thread classes. Which actually use separate processes to work asynchronously, but you shouldn't care about that. You can send events from a thread, return results, use a single thread multiple times, passing it startup arguments, or create a pool of 16 threads raking in your tasks like hot cakes, without paying any attention to the fact that the work is happening in different processes.

In addition, you can easily test the library's performance in different modes, choosing the optimal number of threads and data transfer option between processes specifically for your configuration.

The following extensions are required for full operation: libevent, posix And pcntl.

The library uses LibEvent and paired sockets for communication between processes. Supports 5 options for passing data (arguments, results and event data)!

I present the options immediately with performance data. Tested with a pool of eight threads on an Intel Core i7 2600K 3.40 Ghz (Ubuntu 11.04 on a VMware virtual machine). The average results for 10 repetitions of the test in jps are given (jobs per second - the number of tasks simply receiving arguments and sending data per second).

The extension for working with sockets is automatically selected. If available, the extension is used sockets, which gives improved performance. Otherwise, it will be used stream.

The child process listens to all available signals. By default, all of them (except SIGWINCH and SIGINFO) are followed by shutdown. But this can easily be overridden by creating a method in the thread class with the name of the signal. For example sigWinch.

In the parent process, all signals are also intercepted by default. This can be changed by setting the class parameter listenMasterSignals to false . In this case, only SIGCHLD will be processed. You can easily add your own handlers by creating a static method called m<имя сигнала>. For example, mSigTerm.

If the child process dies for any reason, the class will automatically fork on startup new task. This happens unnoticed and you don’t have to think about it at all. The instance simply does not need to be recreated in case of any error.

The child process periodically checks the existence of the parent process. If it suddenly dies, the child will automatically end.

All resources used by a thread or thread pool are automatically cleaned up when the destructor is called. But they can be cleaned forcibly by calling the cleanup method. In this case, the thread/pool can no longer be used.

At standard settings the thread is initialized in advance, immediately when the class is created. If you set the prefork parameter to false , then the fork will occur only at the moment the task is launched.

In general, there are quite a lot of customizable parameters. Changing the name of the child process after the fork (parameter pName of the constructor), timeout for the duration of the task execution (timeoutWork), timeout for the maximum time the child process waits for tasks (timeoutMaxWait), timeout for the pre-initialization time (timeoutInit), size of buffers for reading sockets (pipeReadSize , pipeMasterReadSize). You can disable multitasking mode for threads (multitask). In this case, each time the task is completed, the child process will die and fork again for the next launch. This will noticeably reduce performance.

The code is covered with tests and documented in detail; examples of use can be viewed and run in the example.php file. More complex examples with error handling can be seen in the unit test code.

There is a debug mode in which very detailed information about what exactly is happening and where.

Examples of using

The main feature is maximum simplicity. If you just want to run something in a separate "thread" the following code is sufficient:

Class ExampleThread extends Thread ( protected function process() ( // Some work here ) ) $thread = new ExampleThread(); $thread->wait()->run();

If there is everything necessary for full-fledged work, then the task will be completed asynchronously. If not, then everything will still work, but in synchronous mode.

By passing a parameter and getting a result, the code will look just a little more complicated:

Class ExampleThread extends Thread ( protected function process() ( return $this->getParam(0); ) ) $thread = new ExampleThread(); $thread->wait()->run(123); $result = $thread->wait()->getResult();

Similarly, with a slight wave of the hand, we add event processing from the stream:

Class ExampleThread extends Thread ( const EV_PROCESS = "process"; protected function process() ( $events = $this->getParam(0); for ($i = 0; $i trigger(self::EV_PROCESS, $event_data); ) ) ) // Additional argument. $additionalArgument = 123; $thread->bind(ExampleThread::EV_PROCESS, function($event_name, $event_data, $additional_arg) ( // event processing), $additionalArgument); $events = 10; // number of events that the thread will generate // To avoid manually waiting for the thread before the first call, // you can override the preforkWait property to TRUE in the descendant class $thread->wait(); $thread = new ExampleThread(); $thread->run($events)->wait();

And finally, using a pool of eight threads with runtime error handling:

$threads = 8 // Number of threads $pool = new ThreadPool("ExampleThread", $threads); $num = 25; // Number of tasks $left = $num; // Number of remaining tasks do ( // If there are free threads in the pool // And we still have tasks to execute while ($pool->hasWaiting() && $left > 0) ( // When starting, we get the thread id $threadId = $pool->run(); $left--; ) if ($results = $pool->wait($failed)) ( foreach ($results as $threadId => $result) ( // Successfully completed task // The result can be identified // by the thread id ($threadId) $num--; ) ) if ($failed) ( // Handle execution errors. // The job is considered to have completed unsuccessfully // if the child process died during execution or // expired timeout for task execution foreach ($failed as $threadId) ( $left++; ) ) ) while ($num > 0); // Terminate all child processes. We clean up the resources used by the pool. $pool->cleanup();

Performance Test Results

I ran the tests on two machines with Ubuntu 11.04.
The first is Intel Core i3 540 3.07 Ghz.
The second is Intel Core i7 2600K 3.40 Ghz (Ubuntu runs on a VMware virtual machine).

I present the results simply so that you can evaluate the increase in productivity. Again, these are the average results for a series of 10 repetitions of the test in jps (jobs per second - number of tasks per second).

As a task, threads perform the following garbage:

For ($i = 0; $i

The first result is indicated for synchronous operation mode (without forks). I didn’t try 18 and 20 threads on the first configuration, since already for 12 the performance began to drop.

Number of threads First configuration Second
0 553 763
1 330 669
2 580 1254
4 1015 2188
8 1040 2618
10 1027 2719
12 970 2739
16 958 2904
18 - 2830
20 - 2730

That is, performance increases by 2-4 times or more, depending on the processor!

The code that runs a series of tests with the required parameters is in the file examples/speed_test.php. So you can easily test performance and choose the optimal number of threads for yourself.

I will be very glad if the library is useful to anyone. Any feature requests or detected bugs can be left on Github, I will promptly fix and improve the library.

There are quite a few solutions floating around the web for emulating multithreading in PHP. Most often they are based on forks, but there are also variations on the theme using curl, proc_open, etc.

For one reason or another, all the options I came across did not suit me and I had to write my own solution.
I had the following set of requirements:

  • Use of forks;
  • Synchronous mode with preservation of the interface in the absence of the necessary extensions;
  • Reuse of child processes;
  • Full data exchange between processes. Those. run with arguments and get the result when finished;
  • The ability to exchange events between a child “thread” process and the main process during operation;
  • Working with a thread pool while maintaining reuse, passing arguments, and getting results;
  • Handling runtime errors;
  • Timeouts for performing work, waiting for work by a thread, initialization;
  • Maximum performance;
The result is a library AzaThread(old name - CThread).

For the impatient, here's a link to the source:
github.com/Anizoptera/AzaThread

Description

AzaThread provides a simple interface for creating thread classes. Which actually use separate processes to work asynchronously, but you shouldn't care about that. You can send events from a thread, return results, use one thread many times passing launch arguments to it, or create a pool of 16 threads raking in your tasks like hot cakes without paying any attention to the fact that the work is happening in different processes.

In addition, you can easily test the library's performance in different modes by selecting the optimal number of threads and the option of transferring data between processes specifically for your configuration.

The following extensions are required for full operation: libevent, posix And pcntl.

The library uses LibEvent and paired sockets for communication between processes. Supports 5 options for passing data (arguments, results and event data)!

I present the options immediately with performance data. Tested with a pool of eight threads on an Intel Core i7 2600K 3.40 Ghz (Ubuntu 11.04 on a VMware virtual machine). The average results for 10 repetitions of the test in jps are given (jobs per second - the number of tasks simply receiving arguments and sending data per second).

The extension for working with sockets is automatically selected. If available, the extension is used sockets, which gives improved performance. Otherwise, it will be used stream.

The child process listens to all available signals. By default, all of them (except SIGWINCH and SIGINFO) are followed by shutdown. But this can easily be overridden by creating a method in the thread class with the name of the signal. For example sigWinch.

In the parent process, all signals are also intercepted by default. This can be changed by setting the class parameter listenMasterSignals to false. In this case, only SIGCHLD will be processed. You can easily add your own handlers by creating a static method called m< имя сигнала > . For example mSigTerm.

If a child process dies for some reason, the class will automatically fork when a new task is launched. This happens unnoticed and you don’t have to think about it at all. The instance simply does not need to be recreated in case of any error.

The child process periodically checks the existence of the parent process. If it suddenly dies, the child will automatically end.

All resources used by a thread or thread pool are automatically cleaned up when the destructor is called. But they can be cleared forcibly by calling the method cleanup. In this case, the thread/pool can no longer be used.

With standard settings, the thread is initialized in advance, immediately when the class is created. If you set the parameter prefork to false, then the fork will occur only at the moment the task is launched.

In general, there are quite a lot of customizable parameters. Changing the name of the child process after a fork (parameter pName constructor), timeout for the duration of the task ( timeoutWork), timeout for the maximum time a child process can wait for tasks ( timeoutMaxWait), timeout for pre-initialization time ( timeoutInit), socket read buffer sizes ( pipeReadSize, pipeMasterReadSize).
You can disable multitasking mode for threads ( multitask). In this case, each time the task is completed, the child process will die and fork again for the next launch. This will noticeably reduce performance.

The code is covered with tests and documented in detail; examples of use can be viewed and run in the file example.php.
More complex examples with error handling can be seen in the unit test code.

There is a debugging mode that displays very detailed information about what exactly is going on and where.

Examples of using

The main feature is maximum simplicity. If you just want to run something in a separate “thread” the following code is enough:
class ExampleThread extends Thread ( protected function process() ( // Some work here ) ) $thread = new ExampleThread(); $thread->wait()->run();
If there is everything necessary for full-fledged work, then the task will be completed asynchronously. If not, then everything will still work, but in synchronous mode.

By passing a parameter and getting the result, the code will look just a little more complicated:
class ExampleThread extends Thread ( protected function process() ( return $this->getParam(0); ) ) $thread = new ExampleThread(); $thread->wait()->run(123); $result = $thread->wait()->getResult();

Similarly, with a slight wave of the hand, we add event processing from the stream:
class ExampleThread extends Thread ( const EV_PROCESS = "process"; protected function process() ( $events = $this->getParam(0); for ($i = 0; $i< $events; $i++) { $event_data = $i; $this->trigger(self::EV_PROCESS, $event_data); ) ) ) // Additional argument. $additionalArgument = 123; $thread->bind(ExampleThread::EV_PROCESS, function($event_name, $event_data, $additional_arg) ( // event processing), $additionalArgument); $events = 10; // number of events that the thread will generate // To avoid manually waiting for the thread before the first call, // you can override the preforkWait property to TRUE in the descendant class $thread->wait(); $thread = new ExampleThread(); $thread->run($events)->wait();

And finally, using a pool of eight threads with runtime error handling:
$threads = 8 // Number of threads $pool = new ThreadPool("ExampleThread", $threads); $num = 25; // Number of tasks $left = $num; // Number of remaining tasks do ( // If there are free threads in the pool // And we still have tasks to execute while ($pool->hasWaiting() && $left > 0) ( // When starting, we get the thread id $threadId = $pool->run(); $left--; ) if ($results = $pool->wait($failed)) ( foreach ($results as $threadId => $result) ( // Successfully completed task // The result can be identified // by the thread id ($threadId) $num--; ) ) if ($failed) ( // Handle execution errors. // The job is considered to have completed unsuccessfully // if the child process died during execution or // expired timeout for task execution foreach ($failed as $threadId) ( $left++; ) ) ) while ($num > 0); // Terminate all child processes. We clean up the resources used by the pool. $pool->cleanup();

Performance Test Results

I ran the tests on two machines with Ubuntu 11.04.
The first one is Intel Core i3 540 3.07 Ghz
The second is Intel Core i7 2600K 3.40 Ghz (Ubuntu runs on a VMware virtual machine)

I present the results simply so that you can evaluate the increase in productivity.
Again, these are the average results for a series of 10 test repetitions in jps (jobs per second - number of tasks per second).

As a task, threads perform the following garbage:
for ($i = 0; $i< 1000; $i++) { $r = mt_rand(0, PHP_INT_MAX) * mt_rand(0, PHP_INT_MAX); }
The first result is indicated for synchronous operation mode (without forks).
I didn’t try 18 and 20 threads on the first configuration, since already for 12 the performance began to drop.

Number of threads First configuration Second
0 553 763
1 330 669
2 580 1254
4 1015 2188
8 1040 2618
10 1027 2719
12 970 2739
16 958 2904
18 - 2830
20 - 2730

That is, performance increases by 2-4 times or more, depending on the processor!

The code that runs a series of tests with the required parameters is in the file examples/speed_test.php. So you can easily test performance and choose the optimal number of threads for yourself.