00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef AMINO_TRANSFORM_H
00023 #define AMINO_TRANSFORM_H
00024
00025 #include <algorithm>
00026
00027 #include <amino/thread.h>
00028 #include <amino/ftask.h>
00029
00030 namespace amino {
00031 template<typename InputIterator, typename OutputIterator,
00032 typename UnaryFunction, typename Executor>
00033 OutputIterator transform(Executor& exec, InputIterator first,
00034 InputIterator last, OutputIterator result, UnaryFunction op) {
00035 int procCount = getProcessNum();
00036 return transform(exec, procCount, first, last, result, op);
00037 }
00038
00039 template<typename InputIterator1, typename InputIterator2,
00040 typename OutputIterator, typename BinaryFunction, typename Executor>
00041 OutputIterator transform(Executor& exec, InputIterator1 first1,
00042 InputIterator1 last1, InputIterator2 first2, OutputIterator result,
00043 BinaryFunction binary_op) {
00044 int procCount = getProcessNum();
00045 return transform(exec, procCount, first1, last1, first2, result, binary_op);
00046 }
00047
00048 template<typename InputIterator, typename OutputIterator,
00049 typename UnaryFunction>
00050 class CallStdTransformUnary: public Runnable {
00051 private:
00052 InputIterator f_first, f_last;
00053 OutputIterator f_result;
00054 UnaryFunction *f_op;
00055
00056 OutputIterator f_result_last;
00057
00058 public:
00059 CallStdTransformUnary() {
00060 }
00061
00062 void setup(InputIterator first, InputIterator last, OutputIterator result,
00063 UnaryFunction& op) {
00064 f_first = first;
00065 f_last = last;
00066 f_result = result;
00067 f_op = &op;
00068 }
00069
00070 OutputIterator getResultLast() {
00071 return f_result_last;
00072 }
00073
00074 void* run() {
00075 f_result_last = std::transform(f_first, f_last, f_result, *f_op);
00076 return NULL;
00077 }
00078 };
00079
00080 template<typename InputIterator1, typename InputIterator2,
00081 typename OutputIterator, typename BinaryFunction>
00082 class CallStdTransformBinary: public Runnable {
00083 private:
00084 InputIterator1 f_first1, f_last1;
00085 InputIterator2 f_first2;
00086 OutputIterator f_result;
00087 BinaryFunction *f_op;
00088
00089 OutputIterator f_result_last;
00090
00091 public:
00092 CallStdTransformBinary() {
00093 }
00094
00095 void setup(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result,BinaryFunction& binary_op) {
00096 f_first1 = first1;
00097 f_last1 = last1;
00098 f_first2 = first2;
00099 f_result = result;
00100 f_op = &binary_op;
00101 }
00102
00103 OutputIterator getResultLast() {
00104 return f_result_last;
00105 }
00106
00107 void* run() {
00108 f_result_last = std::transform(f_first1, f_last1, f_first2, f_result,
00109 *f_op);
00110 return NULL;
00111 }
00112 };
00113
00114 template<typename InputIterator, typename OutputIterator,
00115 typename UnaryFunction, typename Executor>
00116 OutputIterator transform(Executor& exec, int threadNum, InputIterator first,
00117 InputIterator last, OutputIterator result, UnaryFunction op) {
00118 const int MULTI_NUM = 3;
00119
00120 if (last - first < MULTI_NUM * threadNum)
00121 return std::transform(first, last, result, op);
00122
00123 int step = (last - first) / threadNum;
00124
00125 typedef CallStdTransformUnary<InputIterator, OutputIterator, UnaryFunction>
00126 Caller;
00127 Caller* pCallers = new Caller[threadNum];
00128 FutureTask **pFTasks = new FutureTask*[threadNum];
00129
00130 for (int i = 0; i < threadNum - 1; ++i) {
00131 pCallers[i].setup(first + i * step, first + (i + 1) * step, result + i
00132 * step, op);
00133 pFTasks[i] = new FutureTask(pCallers + i);
00134 exec.execute(pFTasks[i]);
00135 }
00136
00137 pCallers[threadNum - 1].setup(first + (threadNum - 1) * step, last, result
00138 + (threadNum - 1) * step, op);
00139 pFTasks[threadNum - 1] = new FutureTask(pCallers + threadNum - 1);
00140 exec.execute(pFTasks[threadNum - 1]);
00141
00142 for (int i = 0; i < threadNum; ++i) {
00143 pFTasks[i] -> get();
00144 }
00145
00146 OutputIterator ret = pCallers[threadNum - 1].getResultLast();
00147
00148 delete[] pCallers;
00149 for (int i = 0; i < threadNum; ++i) {
00150 delete pFTasks[i];
00151 }
00152 delete[] pFTasks;
00153
00154 return ret;
00155 }
00156
00157 template<typename InputIterator1, typename InputIterator2,
00158 typename OutputIterator, typename BinaryFunction, typename Executor>
00159 OutputIterator transform(Executor& exec, int threadNum, InputIterator1 first1,
00160 InputIterator1 last1, InputIterator2 first2, OutputIterator result,
00161 BinaryFunction op) {
00162 const int MULTI_NUM = 3;
00163
00164 if (last1 - first1 < MULTI_NUM * threadNum)
00165 return std::transform(first1, last1, first2, result, op);
00166
00167 int step = (last1 - first1) / threadNum;
00168
00169 typedef CallStdTransformBinary<InputIterator1, InputIterator2,
00170 OutputIterator, BinaryFunction> Caller;
00171 Caller* pCallers = new Caller[threadNum];
00172 FutureTask **pFTasks = new FutureTask*[threadNum];
00173
00174 for (int i = 0; i < threadNum - 1; ++i) {
00175 pCallers[i].setup(first1+i*step, first1+(i+1)*step, first2+i*step, result+i*step, op);
00176 pFTasks[i] = new FutureTask(pCallers + i);
00177 exec.execute(pFTasks[i]);
00178 }
00179
00180 pCallers[threadNum - 1].setup(first1 + (threadNum - 1) * step, last1,
00181 first2 + (threadNum - 1) * step, result + (threadNum - 1) * step,
00182 op);
00183 pFTasks[threadNum - 1] = new FutureTask(pCallers + threadNum - 1);
00184 exec.execute(pFTasks[threadNum - 1]);
00185
00186 for (int i = 0; i < threadNum; ++i) {
00187 pFTasks[i] -> get();
00188 }
00189
00190 OutputIterator ret = pCallers[threadNum - 1].getResultLast();
00191
00192 delete[] pCallers;
00193 for (int i = 0; i < threadNum; ++i) {
00194 delete pFTasks[i];
00195 }
00196 delete[] pFTasks;
00197
00198 return ret;
00199 }
00200
00201 }
00202 ;
00203
00204 #endif