{"id":45094272,"url":"https://github.com/appserver-io/concurrency","last_synced_at":"2026-02-19T18:09:43.159Z","repository":{"id":28935146,"uuid":"32460895","full_name":"appserver-io/concurrency","owner":"appserver-io","description":"It introduces abstract services and objects that provides easy handling for thread-safety, concurrency and sharing.","archived":false,"fork":false,"pushed_at":"2015-06-24T14:47:50.000Z","size":283,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-24T08:43:05.303Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/appserver-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-18T13:37:18.000Z","updated_at":"2016-04-04T08:40:12.000Z","dependencies_parsed_at":"2022-09-05T18:51:24.692Z","dependency_job_id":null,"html_url":"https://github.com/appserver-io/concurrency","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/appserver-io/concurrency","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appserver-io%2Fconcurrency","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appserver-io%2Fconcurrency/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appserver-io%2Fconcurrency/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appserver-io%2Fconcurrency/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/appserver-io","download_url":"https://codeload.github.com/appserver-io/concurrency/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appserver-io%2Fconcurrency/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29626892,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T18:02:07.722Z","status":"ssl_error","status_checked_at":"2026-02-19T18:01:46.144Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-19T18:09:42.133Z","updated_at":"2026-02-19T18:09:43.153Z","avatar_url":"https://github.com/appserver-io.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Toolkit for Concurrent Programming in PHP with pthreads\n\n[![Latest Stable Version](https://img.shields.io/packagist/v/appserver-io/concurrency.svg?style=flat-square)](https://packagist.org/packages/appserver-io/concurrency) \n [![Total Downloads](https://img.shields.io/packagist/dt/appserver-io/concurrency.svg?style=flat-square)](https://packagist.org/packages/appserver-io/concurrency)\n [![License](https://img.shields.io/packagist/l/appserver-io/concurrency.svg?style=flat-square)](https://packagist.org/packages/appserver-io/concurrency)\n [![Build Status](https://img.shields.io/travis/appserver-io/concurrency/master.svg?style=flat-square)](http://travis-ci.org/appserver-io/concurrency)\n [![Code Coverage](https://img.shields.io/codeclimate/github/appserver-io/concurrency.svg?style=flat-square)](https://codeclimate.com/github/appserver-io/concurrency)\n [![Code Quality](https://img.shields.io/codeclimate/coverage/github/appserver-io/concurrency.svg?style=flat-square)](https://codeclimate.com/github/appserver-io/concurrency)\n\n## What is it?\n\nThe concurrency toolkit introduces abstract services and objects that provides easy handling for thread-safety, concurrency programming and data sharing all written in PHP-Userland.\n\n## Why?\n\nIf you are implementing multithreaded functionality you're always fighting against the same problems called Race-Conditions, Deadlocks etc... When sharing simple data or even plain PHP objects between threads you have to make sure, that everything is synchronized (Thread-safe) in any logic of your code. This Toolkit mostly helps you to avoid those problems by providing abstract services and object written in PHP-Userland.\n\n## How to use?\n\nThis toolkit is in early-stage development. Please use with caution.\n\n### The ExecutorService\n\nIt allows you to hold plain PHP objects persistent as singleton in memory accessible everywhere in your code even in different thread contexts. You can keep those plain PHP objects easily thread-safe or call certain methods asynchronous by using simple annotations like `@Synchronized` or `@Asynchronous` in method docblocks.\n\n#### How it works\n\nIf you want to use the concurrency toolkit in your project you have to add it to the composer dependencies `composer.json` and do a `composer update` afterwards.\n\n```javascript\n{\n    \"require\": {\n        \"appserver-io/concurrency\": \"~0.2\"\n    },\n}\n```\n\nAt first you have to initialise the `ExecutorService` in a main PHP script `main.php`.\n```php\n\u003c?php\n\ndefine(AUTOLOADER, 'vendor/autoload.php');\nrequire_once(AUTOLOADER);\n\n// init executor service\n\\AppserverIo\\Concurrecy\\ExecutorService::__init(AUTOLOADER);\n```\n\nLets say you want to build a simple storage PHP object to share data all over your multithreaded implementations. The storage object could look like this. Create `Storage.php` and add:\n\n```php\n\u003c?php\n\nclass Storage\n{\n    public $data = array();\n\n    /**\n     * @Synchronized\n     */\n    public function all() {\n        return $this-\u003edata;\n    }\n\n    /**\n     * @Synchronized\n     */\n    public function set($key, $value) {\n        $this-\u003edata[$key] = $value;\n    }\n\n    /**\n     * @Synchronized\n     */\n    public function get($key) {\n        if ($this-\u003ehas($key)) {\n            return $this-\u003edata[$key];\n        }\n    }\n\n    /**\n     * @Synchronized\n     */\n    public function has($key) {\n        return isset($this-\u003edata[$key]);\n    }\n\n    /**\n     * @Synchronized\n     */\n    public function del($key) {\n        unset($this-\u003edata[$key]);\n    }\n\n    /**\n     * @Synchronized\n     */\n    public function inc($key) {\n        if ($this-\u003ehas($key)) {\n            ++$this-\u003edata[$key];\n        }\n    }\n\n    /**\n     * @Asynchronous\n     */\n    public function dump() {\n        echo var_export($this-\u003eall(), true) . PHP_EOL;\n    }\n}\n```\n\nMaybe you've noticed the method docblock annotations we used here. Methods marked with `@Synchronized` can not be called more than once at the same time. That means the `$data` array will always be synchronized when using `all()`, `set()`, `get()`, `del()` or `inc()`. Methods using `@Asynchronous` are called asynchronously. So if the `dump()` method is called it will dump the `$data` array while not blocking your main logic execution.\n\nTo make use of the storage object we have to create a multithreaded task simulation that should represent multithreaded business logic. So create `Task.php` and add:\n\n```php\n\u003c?php\nclass Task extends Thread {\n\n    public static function simulate($maxThreads) {\n        $t = array();\n        for ($i=0; $i\u003c$maxThreads; $i++) {\n            $t[$i] = new self();\n            $t[$i]-\u003estart(PTHREADS_INHERIT_ALL | PTHREADS_ALLOW_GLOBALS);\n        }\n        for ($i=0; $i\u003c$maxThreads; $i++) {\n            $t[$i]-\u003ejoin();\n        }\n    }\n\n    public function run() {\n        // get the storage object\n        $storage = \\AppserverIo\\Concurrency\\ExecutorService::__getEntity('data');\n        // add thread signature\n        $storage-\u003eset($this-\u003egetThreadId(), __METHOD__);\n        // increase internal counter\n        $storage-\u003einc('counter');\n    }\n}\n```\n\nNow bring all together and enhance the main script `main.php`:\n\n```php\n\u003c?php\n\ndefine('AUTOLOADER', 'vendor/autoload.php');\nrequire_once(AUTOLOADER);\nrequire_once('Storage.php');\nrequire_once('Task.php');\n\nuse \\AppserverIo\\Concurrency\\ExecutorService as ExS;\n\n// init executor service\nExS\\Core::init(AUTOLOADER);\n\n// create storage instance with alias data\n$data = ExS\\Core::newFromEntity('Storage', 'data');\n\n// preinit counter\n$data-\u003eset('counter', 0);\n\n// simulate multithreaded tasks\nTask::simulate(10);\n\n// dump data async\n$data-\u003edump();\n\necho 'finished' . PHP_EOL;\n\n// shutdown executor service and its entities\nExS\\Core::shutdown();\n```\n\nIf you call `main.php` with a thread-safe compiled php version where pthreads ext is installed as\nit`s provided by appserver.io runtime for example the result should look like this:\n\n```bash\n$ /opt/appserver/bin/php bootstrap.php \nfinished\narray (\n  'counter' =\u003e 10,\n  140470559000320 =\u003e 'Task::run',\n  140470550284032 =\u003e 'Task::run',\n  140470541891328 =\u003e 'Task::run',\n  140470327965440 =\u003e 'Task::run',\n  140470319572736 =\u003e 'Task::run',\n  140470311180032 =\u003e 'Task::run',\n  140470302787328 =\u003e 'Task::run',\n  140470294394624 =\u003e 'Task::run',\n  140470286001920 =\u003e 'Task::run',\n  140470277609216 =\u003e 'Task::run',\n)\n```\n\nThe executor service has some internal function as described here:\n\n| Method | Description |\n| ---------- | ----------- |\n| `__return` | Returns the plain entity object from executor thread context if its serializable in its actual state |\n| `__invoke(closure)` | Executes the callable in executor thread context. It will provide $self as function argument which references the plain entity object. Example usage: \u003cpre lang=\"php\"\u003e$executorServiceEntity-\u003e__invoke(function($self) { $self-\u003edoSomething() }); \u003c/pre\u003e |\n| `__reset()` | Resets the plaing entity object in executor service context\n| `__shutdown()` | Shutdown the executor service thread \n\n## Issues\nIn order to bundle our efforts we would like to collect all issues regarding this package in [the main project repository's issue tracker](https://github.com/appserver-io/appserver/issues).\nPlease reference the originating repository as the first element of the issue title e.g.:\n`[appserver-io/\u003cORIGINATING_REPO\u003e] A issue I am having`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappserver-io%2Fconcurrency","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fappserver-io%2Fconcurrency","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappserver-io%2Fconcurrency/lists"}