make (array) of ArrayObject return the contents
[hiphop-php.git] / hphp / util / async-func.h
blob4c3294d500986b994f9caa52c2c505b726bbba78
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_CONCURRENCY_ASYNC_FUNC_H_
18 #define incl_HPHP_CONCURRENCY_ASYNC_FUNC_H_
20 #include "hphp/util/base.h"
21 #include <pthread.h>
22 #include "hphp/util/synchronizable.h"
23 #include "hphp/util/lock.h"
24 #include "hphp/util/exception.h"
25 #include "hphp/util/alloc.h"
27 namespace HPHP {
28 ///////////////////////////////////////////////////////////////////////////////
30 /**
31 * Invokes a function asynchrously. For example,
33 * class MyClass {
34 * public:
35 * void doJob();
36 * };
38 * MyClass obj;
39 * AsyncFunc<MyClass> func(&obj, &MyClasss::doJob);
40 * func.start(); // this will call obj.doJob() in a separate thread
41 * // do something else
42 * func.waitForEnd();
44 * Asynchronous function is a slightly different way of thinking about threads.
45 * Maybe this can help people understand asynchronous function is actually a
46 * broader/identical view of running threads,
48 * class MyRunnable {
49 * public:
50 * void run();
51 * };
53 * MyRunnable thread;
54 * AsyncFunc<Runnable> func(&thread, &MyRunnable::run);
55 * thread.run();
57 * Well, asynchronous function is sometimes more flexible in writing a server,
58 * because it can bind different threads to methods on the same object:
60 * class MyServer {
61 * public:
62 * void thread1();
63 * void thread2();
64 * };
66 * MyServer server;
67 * AsyncFunc<MyServer> func1(&server, &MyServer::thread1);
68 * AsyncFunc<MyServer> func2(&server, &MyServer::thread2);
69 * func1.start();
70 * func2.start();
71 * ...now both threads are running, accessing the same server object.
73 * There is nothing wrong embedding the async function object itself in the
74 * class like this,
76 * class MyServer {
77 * public:
78 * MyServer()
79 * : m_thread1(this, &MyServer::thread1),
80 * : m_thread2(this, &MyServer::thread2) {
81 * }
83 * void thread1();
84 * void thread2();
86 * void start() {
87 * m_thread1.start();
88 * m_thread2.start();
89 * }
91 * private:
92 * AsyncFunc<MyServer> m_thread1;
93 * AsyncFunc<MyServer> m_thread2;
94 * };
97 class AsyncFuncImpl {
98 public:
99 typedef void PFN_THREAD_FUNC(void *);
102 * The global static to feed into pthread_create(), and this will delegate
103 * the work to AsyncFuncImpl::threadFuncImpl().
105 static void *ThreadFunc(void *obj);
108 * Called by AsyncFunc<T> so we can call func(obj) back on thread running.
110 AsyncFuncImpl(void *obj, PFN_THREAD_FUNC *func);
111 ~AsyncFuncImpl();
114 * Starts this thread.
116 void start();
119 * Sends a cancellation request to the thread. NB: Do not use this unless
120 * the function is known to support cancellation and known to leave shared
121 * state in a consistent state (alternatively, the caller should proceed to
122 * shut down the process as well). Also, call waitForEnd following this call
123 * before proceeding as if the async func has stopped executing.
125 void cancel();
128 * Waits until this thread finishes running.
130 bool waitForEnd(int seconds = 0);
133 * Starts and waits until this thread finishes running.
135 void run() {
136 start();
137 waitForEnd();
140 pthread_attr_t *getThreadAttr() {
141 return &m_attr;
144 static void SetThreadInitFunc(PFN_THREAD_FUNC* func, void *arg) {
145 s_initFunc = func;
146 s_initFuncArg = arg;
149 static void SetThreadFiniFunc(PFN_THREAD_FUNC* func, void *arg) {
150 s_finiFunc = func;
151 s_finiFuncArg = arg;
154 static PFN_THREAD_FUNC* GetThreadInitFunc() {
155 return s_initFunc;
158 static PFN_THREAD_FUNC* GetThreadFiniFunc() {
159 return s_finiFunc;
162 void setNoInit() { m_noInit = true; }
163 private:
164 Synchronizable m_stopMonitor;
166 void* m_obj;
167 PFN_THREAD_FUNC* m_func;
168 static PFN_THREAD_FUNC* s_initFunc;
169 static PFN_THREAD_FUNC* s_finiFunc;
170 static void* s_initFuncArg;
171 static void* s_finiFuncArg;
172 void* m_threadStack;
173 pthread_attr_t m_attr;
174 pthread_t m_threadId;
175 Exception* m_exception; // exception was thrown and thread was terminated
176 int m_node;
177 bool m_stopped;
178 bool m_noInit;
180 static const size_t m_stackSizeMinimum = 8388608; // 8MB
183 * Called by ThreadFunc() to delegate the work.
185 void threadFuncImpl();
188 ///////////////////////////////////////////////////////////////////////////////
191 * We could have written AysncFunc<T> directly with those methods implemented
192 * inside AsyncFuncImpl class, but this way we reduce sizes of our code by
193 * only templatizing a very minimal piece of code, sharing everything inside
194 * AsyncFuncImpl by all AsyncFunc<T> classes.
196 template<class T>
197 class AsyncFunc : public AsyncFuncImpl {
198 public:
199 AsyncFunc(T *obj, void (T::*member_func)())
200 : AsyncFuncImpl((void*)this, run_), m_obj(obj), m_memberFunc(member_func) {
203 static void run_(void *obj) {
204 AsyncFunc<T> *p = (AsyncFunc<T>*)obj;
205 (p->m_obj->*(p->m_memberFunc))();
208 private:
209 T *m_obj;
210 void (T::*m_memberFunc)();
213 ///////////////////////////////////////////////////////////////////////////////
216 #endif // incl_HPHP_CONCURRENCY_ASYNC_FUNC_H_