holder.h 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. /*
  2. * @copyright
  3. * Copyright (C) 2011-2013, Intel Corporation
  4. * All rights reserved.
  5. *
  6. * @copyright
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * * Neither the name of Intel Corporation nor the names of its
  18. * contributors may be used to endorse or promote products derived
  19. * from this software without specific prior written permission.
  20. *
  21. * @copyright
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  26. * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  29. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  30. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  32. * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. */
  36. /*
  37. * holder.h
  38. *
  39. * Purpose: hyperobject to provide different views of an object to each
  40. * parallel strand.
  41. */
  42. #ifndef HOLDER_H_INCLUDED
  43. #define HOLDER_H_INCLUDED
  44. #include <cilk/reducer.h>
  45. #include <memory>
  46. #include <utility>
  47. #ifdef __cplusplus
  48. /* C++ Interface
  49. *
  50. * Classes: holder<Type>
  51. *
  52. * Description:
  53. * ============
  54. * This component provides a hyperobject that isolates a parallel uses of a
  55. * common variable where it is not necessary to preserve changes from
  56. * different parallel strands. In effect, a holder acts a bit like
  57. * thread-local storage, but has qualities that work better with the
  58. * fork-join structure of Cilk. In particular, a holder has the following
  59. * qualities:
  60. *
  61. * - The view of a holder before the first spawn within a function is the same
  62. * as the view after each sync (as in the case of a reducer).
  63. * - The view of a holder within the first spawned child of a function (or the
  64. * first child spawned after a sync) is the same as the view on entry to the
  65. * function.
  66. * - The view of a holder before entering a _Cilk_for loop is the same as the
  67. * view during the first iteration of the loop and the view at the end of
  68. * the loop.
  69. * - The view of a holder in the continuation of a spawn or in an arbitrary
  70. * iteration of a _Cilk_for loop is *non-deterministic*. It is generally
  71. * recommended that the holder be explicitly put into a known state in these
  72. * situations.
  73. *
  74. * A holder can be used as an alternative to parameter-passing. They are most
  75. * useful for replacing non-local variables without massive refactoring. A
  76. * holder takes advantage of the fact that, most of the time, a holder view
  77. * does not change after a spawn or from one iteration of a parallel for loop
  78. * to the next (i.e., stealing is the exception, not the rule). When the
  79. * holder view is a large object that is expensive to construct, this
  80. * optimization can save significant time versus creating a separate local
  81. * object for each view. In addition, a holder using the "keep last" policy
  82. * will have the same value after a sync as the serialization of the same
  83. * program. The last quality will often allow the program to avoid
  84. * recomputing a value.
  85. *
  86. * Usage Example:
  87. * ==============
  88. * Function 'compute()' is a complex function that computes a value using a
  89. * memoized algorithm, storing intermediate results in a hash table. Compute
  90. * calls several other functions, each of which calls several other functions,
  91. * all of which share a global hash table. In all, there are over a dozen
  92. * functions with a total of about 60 references to the hash table.
  93. *..
  94. * hash_table<int, X> memos;
  95. *
  96. * void h(const X& x); // Uses memos
  97. *
  98. * double compute(const X& x)
  99. * {
  100. * memos.clear();
  101. * // ...
  102. * memos[i] = x;
  103. * ...
  104. * g(i); // Uses memos
  105. * // ...
  106. * std::for_each(c.begin(), c.end(), h); // Call h for each element of c
  107. * }
  108. *
  109. * int main()
  110. * {
  111. * const std::size_t ARRAY_SIZE = 1000000;
  112. * extern X myArray[ARRAY_SIZE];
  113. *
  114. * for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
  115. * {
  116. * compute(myArray[i]);
  117. * }
  118. * }
  119. *..
  120. * We would like to replace the 'for' loop in 'main' with a 'cilk_for'.
  121. * Although the hash table is cleared on entry to each call to 'compute()',
  122. * and although the values stored in the hash table are no longer used after
  123. * 'compute()' returns, the use of the hash table as a global variable
  124. * prevents 'compute()' from being called safely in parallel. One way to do
  125. * this would be to make 'memos' a private variable within the cilk_for loop
  126. * and pass it down to the actual computation, so that each loop iteration has
  127. * its own private copy:
  128. *..
  129. * cilk_for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
  130. * {
  131. * hash_table<int, X> memos;
  132. * compute(myArray[i], memos);
  133. * }
  134. *..
  135. * The problem with this approach is that it requires changing the signature
  136. * of 'compute', 'h', 'g', and every one of the dozen or so functions that
  137. * reference 'memos' as well as any function that calls those functions. This
  138. * may break the abstraction of 'compute' and other functions, exposing an
  139. * implementation detail that was not part of the interface. In addition, the
  140. * function 'h' is called through a templated algorithm, 'for_each', which
  141. * requires a fixed interface. Finally, there is constructor and destructor
  142. * overhead for 'hash_table' each time through the loop.
  143. *
  144. * The alternative approach is to replace 'memos' with a holder. The holder
  145. * would be available to all of the functions involved, but would not cause a
  146. * race between parallel loop iterations. In order to make this work, each
  147. * use of the 'memos' variable must be (mechanically) replaced by a use of the
  148. * holder:
  149. *..
  150. * cilk::holder<hash_table<int, X> > memos_h;
  151. *
  152. * void h(const X& x); // Uses memos_h
  153. *
  154. * double compute(const X& x)
  155. * {
  156. * memos_h().clear(); // operator() used to "dereference" the holder
  157. * // ...
  158. * memos_h()[i] = x; // operator() used to "dereference" the holder
  159. * ...
  160. * g(i); // Uses memos_h
  161. * // ...
  162. * std::for_each(c.begin(), c.end(), h); // Call h for each element of c
  163. * }
  164. *..
  165. * Note that each reference to the holder must be modified with an empty pair
  166. * of parenthesis. This syntax is needed because there is no facility in C++
  167. * for a "smart reference" that would allow 'memos_h' to be a perfect
  168. * replacement for 'memos'. One way that a user can avoid this syntax change
  169. * is to wrap the holder in a class that has the same inteface as
  170. * 'hash_table' but redirects all calls to the holder:
  171. *..
  172. * template <typename K, typename V>
  173. * class hash_table_holder
  174. * {
  175. * private:
  176. * cilk::holder<hash_table<K, V> > m_holder;
  177. * public:
  178. * void clear() { m_holder().clear(); }
  179. * V& operator[](const K& x) { return m_holder()[x]; }
  180. * std::size_t size() const { return m_holder().size(); }
  181. * // etc. ...
  182. * };
  183. *..
  184. * Using the above wrapper, the original code can be left unchanged except for
  185. * replacing 'hash_table' with 'hash_table_holder' and replacing 'for' with
  186. * 'cilk_for':
  187. *..
  188. * hash_table_holder<int, X> memos;
  189. *
  190. * void h(const X& x); // Uses memos
  191. *
  192. * double compute(const X& x)
  193. * {
  194. * memos.clear(); // Calls hash_table_holder::clear().
  195. * // ...
  196. * }
  197. *..
  198. * The above changes have no benefit over the use of thread-local storage.
  199. * What if one of the functions has a 'cilk_spawn', however?
  200. *..
  201. * void h(const X& x)
  202. * {
  203. * Y y = x.nested();
  204. * double d, w;
  205. * if (y)
  206. * {
  207. * w = cilk_spawn compute_width(y); // May use 'memos'
  208. * d = compute_depth(y); // Does not use 'memos'
  209. * cilk_sync;
  210. * compute(y); // recursive call. Uses 'memos'.
  211. * }
  212. * }
  213. *..
  214. * In the above example, the view of the holder within 'compute_width' is the
  215. * same as the view on entry to 'h'. More importantly, the view of the holder
  216. * within the recursive call to 'compute' is the same as the view on entry to
  217. * 'h', even if a different worker is executing the recursive call. Thus, the
  218. * holder view within a Cilk program has useful qualities not found in
  219. * thread-local storage.
  220. */
  221. namespace cilk {
  222. /**
  223. * After a sync, the value stored in a holder matches the most recent
  224. * value stored into the holder by one of the starnds entering the sync.
  225. * The holder policy used to instantiate the holder determines which of
  226. * the entering strands determines the final value of the holder. A policy
  227. * of 'holder_keep_indeterminate' (the default) is the most efficient, and
  228. * results in an indeterminate value depending on the runtime schedule
  229. * (see below for more specifics). An indeterminate value after a sync is
  230. * often acceptable, especially if the value of the holder is not reused
  231. * after the sync. All of the remaining policies retain the value of the
  232. * last strand that would be executed in the serialization of the program.
  233. * They differ in the mechanism used to move the value from one view to
  234. * another. A policy of 'holder_keep_last_copy' moves values by
  235. * copy-assignment. A policy of 'holder_keep_last_swap' moves values by
  236. * calling 'swap'. A policy of 'holder_keep_last_move' is available only
  237. * for compilers that support C++0x rvalue references and moves values by
  238. * move-assignment. A policy of 'holder_keep_last' attempts to choose the
  239. * most efficient mechanism: member-function 'swap' if the view type
  240. * supports it, otherwise move-assignment if supported, otherwise
  241. * copy-assignment. (The swap member function for a class that provides
  242. * one is almost always as fast or faster than move-assignment or
  243. * copy-assignment.)
  244. *
  245. * The behavior of 'holder_keep_indeterminate', while indeterminate, is
  246. * not random and can be used for advanced programming or debugging. With
  247. * a policy of 'holder_keep_intermediate', values are never copied or
  248. * moved between views. The value of the view after a sync is the same as
  249. * the value set in the last spawned child before a steal occurs or the
  250. * last value set in the continuation if no steal occurs. Using this
  251. * knowledge, a programmer can use a holder to detect the earliest steal
  252. * in a piece of code. An indeterminate holder is also useful for keeping
  253. * cached data similar to the way some applications might use thread-local
  254. * storage.
  255. */
  256. enum holder_policy {
  257. holder_keep_indeterminate,
  258. holder_keep_last,
  259. holder_keep_last_copy,
  260. holder_keep_last_swap,
  261. #ifdef __CILKRTS_RVALUE_REFERENCES
  262. holder_keep_last_move
  263. #endif
  264. };
  265. namespace internal {
  266. // Private special-case holder policy using the swap member-function
  267. const holder_policy holder_keep_last_member_swap =
  268. (holder_policy) (holder_keep_last_swap | 0x10);
  269. /* The constant, 'has_member_swap<T>::value', will be 'true' if 'T'
  270. * has a non-static member function with prototype 'void swap(T&)'.
  271. * The mechanism used to detect 'swap' is the most portable among
  272. * present-day compilers, but is not the most robust. Specifically,
  273. * the prototype for 'swap' must exactly match 'void swap(T&)'.
  274. * Near-matches like a 'swap' function that returns 'int' instead of
  275. * 'void' will not be detected. Detection will also fail if 'T'
  276. * inherits 'swap' from a base class.
  277. */
  278. template <typename T>
  279. class has_member_swap
  280. {
  281. // This technique for detecting member functions was described by
  282. // Rani Sharoni in comp.lang.c++.moderated:
  283. // http://groups.google.com/group/comp.lang.c++.moderated/msg/2b06b2432fddfb60
  284. // sizeof(notchar) is guaranteed larger than 1
  285. struct notchar { char x[2]; };
  286. // Instantiationg Q<U, &U::swap> will fail unless U contains a
  287. // non-static member with prototype 'void swap(U&)'.
  288. template <class U, void (U::*)(U&)> struct Q { };
  289. // First 'test' is preferred overload if U::swap exists with the
  290. // correct prototype. Second 'test' is preferred overload
  291. // otherwise.
  292. template <typename U> static char test(Q<U,&U::swap>*);
  293. template <typename U> static notchar test(...);
  294. public:
  295. /// 'value' will be true if T has a non-static member function
  296. /// with prototype 'void swap(T&)'.
  297. static const bool value = (1 == sizeof(test<T>(0)));
  298. };
  299. template <typename T> const bool has_member_swap<T>::value;
  300. /**
  301. * @brief Utility class for exception safety.
  302. *
  303. * The constuctor for this class takes a pointer and an allocator and
  304. * holds on to them. The destructor deallocates the pointed-to
  305. * object, without calling its destructor, typically to recover memory
  306. * in case an exception is thrown. The release member clears the
  307. * pointer so that the deallocation is prevented, i.e., when the
  308. * exception danger has passed. The behavior of this class is similar
  309. * to auto_ptr and unique_ptr.
  310. */
  311. template <typename Type, typename Allocator = std::allocator<Type> >
  312. class auto_deallocator
  313. {
  314. Allocator m_alloc;
  315. Type* m_ptr;
  316. // Non-copiable
  317. auto_deallocator(const auto_deallocator&);
  318. auto_deallocator& operator=(const auto_deallocator&);
  319. public:
  320. /// Constructor
  321. explicit auto_deallocator(Type* p, const Allocator& a = Allocator())
  322. : m_alloc(a), m_ptr(p) { }
  323. /// Destructor - free allocated resources
  324. ~auto_deallocator() { if (m_ptr) m_alloc.deallocate(m_ptr, 1); }
  325. /// Remove reference to resource
  326. void release() { m_ptr = 0; }
  327. };
  328. /**
  329. * Pure-abstract base class to initialize holder views
  330. */
  331. template <typename Type, typename Allocator>
  332. class init_base
  333. {
  334. public:
  335. virtual ~init_base() { }
  336. virtual init_base* clone_self(Allocator& a) const = 0;
  337. virtual void delete_self(Allocator& a) = 0;
  338. virtual void construct_view(Type* p, Allocator& a) const = 0;
  339. };
  340. /**
  341. * Class to default-initialize a holder view
  342. */
  343. template <typename Type, typename Allocator>
  344. class default_init : public init_base<Type, Allocator>
  345. {
  346. typedef init_base<Type, Allocator> base;
  347. /// Private constructor (called from static make() function).
  348. default_init() { }
  349. // Non-copiable
  350. default_init(const default_init&);
  351. default_init& operator=(const default_init&);
  352. public:
  353. // Static factory function
  354. static default_init* make(Allocator& a);
  355. // Virtual function overrides
  356. virtual ~default_init();
  357. virtual base* clone_self(Allocator& a) const;
  358. virtual void delete_self(Allocator& a);
  359. virtual void construct_view(Type* p, Allocator& a) const;
  360. };
  361. template <typename Type, typename Allocator>
  362. default_init<Type, Allocator>*
  363. default_init<Type, Allocator>::make(Allocator&)
  364. {
  365. // Return a pointer to a singleton. All instances of this class
  366. // are identical, so we need only one.
  367. static default_init self;
  368. return &self;
  369. }
  370. template <typename Type, typename Allocator>
  371. default_init<Type, Allocator>::~default_init()
  372. {
  373. }
  374. template <typename Type, typename Allocator>
  375. init_base<Type, Allocator>*
  376. default_init<Type, Allocator>::clone_self(Allocator& a) const
  377. {
  378. return make(a);
  379. }
  380. template <typename Type, typename Allocator>
  381. void default_init<Type, Allocator>::delete_self(Allocator&)
  382. {
  383. // Since make() returned a shared singleton, there is nothing to
  384. // delete here.
  385. }
  386. template <typename Type, typename Allocator>
  387. void
  388. default_init<Type, Allocator>::construct_view(Type* p,
  389. Allocator&) const
  390. {
  391. ::new((void*) p) Type();
  392. // TBD: In a C++0x library, this should be rewritten
  393. // std::allocator_traits<Allocator>::construct(a, p);
  394. }
  395. /**
  396. * Class to copy-construct a view from a stored exemplar.
  397. */
  398. template <typename Type, typename Allocator>
  399. class exemplar_init : public init_base<Type, Allocator>
  400. {
  401. typedef init_base<Type, Allocator> base;
  402. Type* m_exemplar;
  403. // Private constructors (called from make() functions).
  404. exemplar_init(const Type& val, Allocator& a);
  405. #ifdef __CILKRTS_RVALUE_REFERENCES
  406. exemplar_init(Type&& val, Allocator& a);
  407. #endif
  408. // Non-copyiable
  409. exemplar_init(const exemplar_init&);
  410. exemplar_init& operator=(const exemplar_init&);
  411. public:
  412. // Static factory functions
  413. static exemplar_init* make(const Type& val,
  414. Allocator& a = Allocator());
  415. #ifdef __CILKRTS_RVALUE_REFERENCES
  416. static exemplar_init* make(Type&& val,
  417. Allocator& a = Allocator());
  418. #endif
  419. // Virtual function overrides
  420. virtual ~exemplar_init();
  421. virtual base* clone_self(Allocator& a) const;
  422. virtual void delete_self(Allocator& a);
  423. virtual void construct_view(Type* p, Allocator& a) const;
  424. };
  425. template <typename Type, typename Allocator>
  426. exemplar_init<Type, Allocator>::exemplar_init(const Type& val,
  427. Allocator& a)
  428. {
  429. m_exemplar = a.allocate(1);
  430. auto_deallocator<Type, Allocator> guard(m_exemplar, a);
  431. a.construct(m_exemplar, val);
  432. guard.release();
  433. }
  434. #ifdef __CILKRTS_RVALUE_REFERENCES
  435. template <typename Type, typename Allocator>
  436. exemplar_init<Type, Allocator>::exemplar_init(Type&& val,
  437. Allocator& a)
  438. {
  439. m_exemplar = a.allocate(1);
  440. auto_deallocator<Type, Allocator> guard(m_exemplar, a);
  441. a.construct(m_exemplar, std::forward<Type>(val));
  442. guard.release();
  443. }
  444. #endif
  445. template <typename Type, typename Allocator>
  446. exemplar_init<Type, Allocator>*
  447. exemplar_init<Type, Allocator>::make(const Type& val,
  448. Allocator& a)
  449. {
  450. typedef typename Allocator::template rebind<exemplar_init>::other
  451. self_alloc_t;
  452. self_alloc_t alloc(a);
  453. exemplar_init *self = alloc.allocate(1);
  454. auto_deallocator<exemplar_init, self_alloc_t> guard(self, alloc);
  455. // Don't use allocator to construct self. Allocator should be
  456. // used only on elements of type 'Type'.
  457. ::new((void*) self) exemplar_init(val, a);
  458. guard.release();
  459. return self;
  460. }
  461. #ifdef __CILKRTS_RVALUE_REFERENCES
  462. template <typename Type, typename Allocator>
  463. exemplar_init<Type, Allocator>*
  464. exemplar_init<Type, Allocator>::make(Type&& val,
  465. Allocator& a)
  466. {
  467. typedef typename Allocator::template rebind<exemplar_init>::other
  468. self_alloc_t;
  469. self_alloc_t alloc(a);
  470. exemplar_init *self = alloc.allocate(1);
  471. auto_deallocator<exemplar_init, self_alloc_t> guard(self, alloc);
  472. // Don't use allocator to construct self. Allocator should be
  473. // used only on elements of type 'Type'.
  474. ::new((void*) self) exemplar_init(std::forward<Type>(val), a);
  475. guard.release();
  476. return self;
  477. }
  478. #endif
  479. template <typename Type, typename Allocator>
  480. exemplar_init<Type, Allocator>::~exemplar_init()
  481. {
  482. // Called only by delete_self, which deleted the exemplar using an
  483. // allocator.
  484. __CILKRTS_ASSERT(0 == m_exemplar);
  485. }
  486. template <typename Type, typename Allocator>
  487. init_base<Type, Allocator>*
  488. exemplar_init<Type, Allocator>::clone_self(Allocator& a) const
  489. {
  490. return make(*m_exemplar, a);
  491. }
  492. template <typename Type, typename Allocator>
  493. void exemplar_init<Type, Allocator>::delete_self(Allocator& a)
  494. {
  495. typename Allocator::template rebind<exemplar_init>::other alloc(a);
  496. a.destroy(m_exemplar);
  497. a.deallocate(m_exemplar, 1);
  498. m_exemplar = 0;
  499. this->~exemplar_init();
  500. alloc.deallocate(this, 1);
  501. }
  502. template <typename Type, typename Allocator>
  503. void
  504. exemplar_init<Type, Allocator>::construct_view(Type* p,
  505. Allocator& a) const
  506. {
  507. a.construct(p, *m_exemplar);
  508. // TBD: In a C++0x library, this should be rewritten
  509. // std::allocator_traits<Allocator>::construct(a, p, *m_exemplar);
  510. }
  511. /**
  512. * Class to construct a view using a stored functor. The functor,
  513. * 'f', must be be invokable using the expression 'Type x = f()'.
  514. */
  515. template <typename Func, typename Allocator>
  516. class functor_init :
  517. public init_base<typename Allocator::value_type, Allocator>
  518. {
  519. typedef typename Allocator::value_type value_type;
  520. typedef init_base<value_type, Allocator> base;
  521. typedef typename Allocator::template rebind<Func>::other f_alloc;
  522. Func *m_functor;
  523. /// Private constructors (called from make() functions
  524. functor_init(const Func& f, Allocator& a);
  525. #ifdef __CILKRTS_RVALUE_REFERENCES
  526. functor_init(Func&& f, Allocator& a);
  527. #endif
  528. // Non-copiable
  529. functor_init(const functor_init&);
  530. functor_init& operator=(const functor_init&);
  531. public:
  532. // Static factory functions
  533. static functor_init* make(const Func& val,
  534. Allocator& a = Allocator());
  535. #ifdef __CILKRTS_RVALUE_REFERENCES
  536. static functor_init* make(Func&& val,
  537. Allocator& a = Allocator());
  538. #endif
  539. // Virtual function overrides
  540. virtual ~functor_init();
  541. virtual base* clone_self(Allocator& a) const;
  542. virtual void delete_self(Allocator& a);
  543. virtual void
  544. construct_view(value_type* p, Allocator& a) const;
  545. };
  546. /// Specialization to strip off reference from 'Func&'.
  547. template <typename Func, typename Allocator>
  548. struct functor_init<Func&, Allocator>
  549. : functor_init<Func, Allocator> { };
  550. /// Specialization to strip off reference and cvq from 'const Func&'.
  551. template <typename Func, typename Allocator>
  552. struct functor_init<const Func&, Allocator>
  553. : functor_init<Func, Allocator> { };
  554. template <typename Func, typename Allocator>
  555. functor_init<Func, Allocator>::functor_init(const Func& f,
  556. Allocator& a)
  557. {
  558. f_alloc alloc(a);
  559. m_functor = alloc.allocate(1);
  560. auto_deallocator<Func, f_alloc> guard(m_functor, alloc);
  561. alloc.construct(m_functor, f);
  562. guard.release();
  563. }
  564. #ifdef __CILKRTS_RVALUE_REFERENCES
  565. template <typename Func, typename Allocator>
  566. functor_init<Func, Allocator>::functor_init(Func&& f,
  567. Allocator& a)
  568. {
  569. f_alloc alloc(a);
  570. m_functor = alloc.allocate(1);
  571. auto_deallocator<Func, f_alloc> guard(m_functor, alloc);
  572. alloc.construct(m_functor, std::forward<Func>(f));
  573. guard.release();
  574. }
  575. #endif
  576. template <typename Func, typename Allocator>
  577. functor_init<Func, Allocator>*
  578. functor_init<Func, Allocator>::make(const Func& f, Allocator& a)
  579. {
  580. typedef typename Allocator::template rebind<functor_init>::other
  581. self_alloc_t;
  582. self_alloc_t alloc(a);
  583. functor_init *self = alloc.allocate(1);
  584. auto_deallocator<functor_init, self_alloc_t> guard(self, alloc);
  585. // Don't use allocator to construct self. Allocator should be
  586. // used only on elements of type 'Func'.
  587. ::new((void*) self) functor_init(f, a);
  588. guard.release();
  589. return self;
  590. }
  591. #ifdef __CILKRTS_RVALUE_REFERENCES
  592. template <typename Func, typename Allocator>
  593. functor_init<Func, Allocator>*
  594. functor_init<Func, Allocator>::make(Func&& f, Allocator& a)
  595. {
  596. typedef typename Allocator::template rebind<functor_init>::other
  597. self_alloc_t;
  598. self_alloc_t alloc(a);
  599. functor_init *self = alloc.allocate(1);
  600. auto_deallocator<functor_init, self_alloc_t> guard(self, alloc);
  601. // Don't use allocator to construct self. Allocator should be
  602. // used only on elements of type 'Func'.
  603. ::new((void*) self) functor_init(std::forward<Func>(f), a);
  604. guard.release();
  605. return self;
  606. }
  607. #endif
  608. template <typename Func, typename Allocator>
  609. functor_init<Func, Allocator>::~functor_init()
  610. {
  611. // Called only by delete_self, which deleted the functor using an
  612. // allocator.
  613. __CILKRTS_ASSERT(0 == m_functor);
  614. }
  615. template <typename Func, typename Allocator>
  616. init_base<typename Allocator::value_type, Allocator>*
  617. functor_init<Func, Allocator>::clone_self(Allocator& a) const
  618. {
  619. return make(*m_functor, a);
  620. }
  621. template <typename Func, typename Allocator>
  622. inline
  623. void functor_init<Func, Allocator>::delete_self(Allocator& a)
  624. {
  625. typename Allocator::template rebind<functor_init>::other alloc(a);
  626. f_alloc fa(a);
  627. fa.destroy(m_functor);
  628. fa.deallocate(m_functor, 1);
  629. m_functor = 0;
  630. this->~functor_init();
  631. alloc.deallocate(this, 1);
  632. }
  633. template <typename Func, typename Allocator>
  634. void functor_init<Func, Allocator>::construct_view(value_type* p,
  635. Allocator& a) const
  636. {
  637. a.construct(p, (*m_functor)());
  638. // In C++0x, the above should be written
  639. // std::allocator_traits<Allocator>::construct(a, p, m_functor());
  640. }
  641. /**
  642. * Functor called to reduce a holder
  643. */
  644. template <typename Type, holder_policy Policy>
  645. struct holder_reduce_functor;
  646. /**
  647. * Specialization to keep the left (first) value.
  648. */
  649. template <typename Type>
  650. struct holder_reduce_functor<Type, holder_keep_indeterminate>
  651. {
  652. void operator()(Type* left, Type* right) const { }
  653. };
  654. /**
  655. * Specialization to copy-assign from the right (last) value.
  656. */
  657. template <typename Type>
  658. struct holder_reduce_functor<Type, holder_keep_last_copy>
  659. {
  660. void operator()(Type* left, Type* right) const {
  661. *left = *right;
  662. }
  663. };
  664. /*
  665. * Specialization to keep the right (last) value via swap.
  666. */
  667. template <typename Type>
  668. struct holder_reduce_functor<Type, holder_keep_last_swap>
  669. {
  670. void operator()(Type* left, Type* right) const {
  671. using std::swap;
  672. swap(*left, *right);
  673. }
  674. };
  675. #ifdef __CILKRTS_RVALUE_REFERENCES
  676. /*
  677. * Specialization to move-assign from the right (last) value.
  678. */
  679. template <typename Type>
  680. struct holder_reduce_functor<Type, holder_keep_last_move>
  681. {
  682. void operator()(Type* left, Type* right) const {
  683. *left = std::move(*right);
  684. }
  685. };
  686. #endif
  687. /*
  688. * Specialization to keep the right (last) value via the swap member
  689. * function.
  690. */
  691. template <typename Type>
  692. struct holder_reduce_functor<Type, holder_keep_last_member_swap>
  693. {
  694. void operator()(Type* left, Type* right) const {
  695. left->swap(*right);
  696. }
  697. };
  698. /*
  699. * Specialization to keep the right (last) value by the most efficient
  700. * means detectable.
  701. */
  702. template <typename Type>
  703. struct holder_reduce_functor<Type, holder_keep_last> :
  704. holder_reduce_functor<Type,
  705. (holder_policy)
  706. (has_member_swap<Type>::value ?
  707. holder_keep_last_member_swap :
  708. #ifdef __CILKRTS_RVALUE_REFERENCES
  709. holder_keep_last_move
  710. #else
  711. holder_keep_last_copy
  712. #endif
  713. )>
  714. {
  715. };
  716. } // end namespace internal
  717. /**
  718. * Monoid for holders.
  719. * Allocator type is required to be thread-safe.
  720. */
  721. template <typename Type,
  722. holder_policy Policy = holder_keep_indeterminate,
  723. typename Allocator = std::allocator<Type> >
  724. class holder_monoid : public monoid_base<Type>
  725. {
  726. // Allocator is mutable because the copy of the monoid inside the
  727. // reducer is const (to avoid races on the shared state). However,
  728. // the allocator is required to be thread-safe, so it is ok (and
  729. // necessary) to modify.
  730. mutable Allocator m_allocator;
  731. internal::init_base<Type, Allocator> *m_initializer;
  732. public:
  733. /// This constructor uses default-initialization for both the leftmost
  734. /// view and each identity view.
  735. holder_monoid(const Allocator& a = Allocator())
  736. : m_allocator(a)
  737. , m_initializer(
  738. internal::default_init<Type, Allocator>::make(m_allocator))
  739. { }
  740. /// These constructors use 'val' as an exemplar to copy-construct both
  741. /// the leftmost view and each identity view.
  742. holder_monoid(const Type& val, const Allocator& a = Allocator())
  743. : m_allocator(a)
  744. , m_initializer(internal::exemplar_init<Type, Allocator>::make(
  745. val, m_allocator)) { }
  746. /// This constructor uses 'f' as a functor to construct both
  747. /// the leftmost view and each identity view.
  748. template <typename Func>
  749. holder_monoid(const Func& f, const Allocator& a = Allocator())
  750. : m_allocator(a)
  751. , m_initializer(
  752. internal::functor_init<Func, Allocator>::make(f,m_allocator))
  753. { }
  754. /// Copy constructor
  755. holder_monoid(const holder_monoid& rhs)
  756. : m_allocator(rhs.m_allocator)
  757. , m_initializer(rhs.m_initializer->clone_self(m_allocator)) { }
  758. /// "Extended" copy constructor with allocator
  759. holder_monoid(const holder_monoid& rhs, const Allocator& a)
  760. : m_allocator(a)
  761. , m_initializer(rhs.m_initializer->clone_self(m_allocator)) { }
  762. #ifdef __CILKRTS_RVALUE_REFERENCES
  763. /// Move constructor
  764. holder_monoid(holder_monoid&& rhs)
  765. : m_allocator(rhs.m_allocator)
  766. , m_initializer(rhs.m_initializer) {
  767. rhs.m_initializer =
  768. internal::default_init<Type, Allocator>::make(m_allocator);
  769. }
  770. /// "Extended" move constructor with allocator
  771. holder_monoid(holder_monoid&& rhs, const Allocator& a)
  772. : m_allocator(a)
  773. , m_initializer(0) {
  774. if (a != rhs.m_allocator)
  775. m_initializer = rhs.m_initializer->clone_self(a);
  776. else {
  777. m_initializer = rhs.m_initializer;
  778. rhs.m_initializer =
  779. internal::default_init<Type, Allocator>::make(m_allocator);
  780. }
  781. }
  782. #endif
  783. /// Destructor
  784. ~holder_monoid() { m_initializer->delete_self(m_allocator); }
  785. holder_monoid& operator=(const holder_monoid& rhs) {
  786. if (this == &rhs) return *this;
  787. m_initializer->delete_self(m_allocator);
  788. m_initializer = rhs.m_initializer->clone_self(m_allocator);
  789. }
  790. #ifdef __CILKRTS_RVALUE_REFERENCES
  791. holder_monoid& operator=(holder_monoid&& rhs) {
  792. if (m_allocator != rhs.m_allocator)
  793. // Delegate to copy-assignment on unequal allocators
  794. return operator=(static_cast<const holder_monoid&>(rhs));
  795. std::swap(m_initializer, rhs.m_initializer);
  796. return *this;
  797. }
  798. #endif
  799. /// Constructs IDENTITY value into the uninitilized '*p'
  800. void identity(Type* p) const
  801. { m_initializer->construct_view(p, m_allocator); }
  802. /// Calls the destructor on the object pointed-to by 'p'
  803. void destroy(Type* p) const
  804. { m_allocator.destroy(p); }
  805. /// Return a pointer to size bytes of raw memory
  806. void* allocate(std::size_t s) const {
  807. __CILKRTS_ASSERT(sizeof(Type) == s);
  808. return m_allocator.allocate(1);
  809. }
  810. /// Deallocate the raw memory at p
  811. void deallocate(void* p) const {
  812. m_allocator.deallocate(static_cast<Type*>(p), sizeof(Type));
  813. }
  814. void reduce(Type* left, Type* right) const {
  815. internal::holder_reduce_functor<Type, Policy>()(left, right);
  816. }
  817. void swap(holder_monoid& other) {
  818. __CILKRTS_ASSERT(m_allocator == other.m_allocator);
  819. std::swap(m_initializer, other.m_initializer);
  820. }
  821. Allocator get_allocator() const {
  822. return m_allocator;
  823. }
  824. };
  825. // Namespace-scope swap
  826. template <typename Type, holder_policy Policy, typename Allocator>
  827. inline void swap(holder_monoid<Type, Policy, Allocator>& a,
  828. holder_monoid<Type, Policy, Allocator>& b)
  829. {
  830. a.swap(b);
  831. }
  832. /**
  833. * Hyperobject to provide different views of an object to each
  834. * parallel strand.
  835. */
  836. template <typename Type,
  837. holder_policy Policy = holder_keep_indeterminate,
  838. typename Allocator = std::allocator<Type> >
  839. class holder : public reducer<holder_monoid<Type, Policy, Allocator> >
  840. {
  841. typedef holder_monoid<Type, Policy, Allocator> monoid_type;
  842. typedef reducer<monoid_type> imp;
  843. // Return a value of Type constructed using the functor Func.
  844. template <typename Func>
  845. Type make_value(const Func& f) const {
  846. struct obj {
  847. union {
  848. char buf[sizeof(Type)];
  849. void* align1;
  850. double align2;
  851. };
  852. obj(const Func& f) { f(static_cast<Type*>(buf)); }
  853. ~obj() { static_cast<Type*>(buf)->~Type(); }
  854. operator Type&() { return *static_cast<Type*>(buf); }
  855. };
  856. return obj(f);
  857. }
  858. public:
  859. /// Default constructor uses default-initialization for both the
  860. /// leftmost view and each identity view.
  861. holder(const Allocator& alloc = Allocator())
  862. : imp(monoid_type(alloc)) { }
  863. /// Construct from an exemplar that is used to initialize both the
  864. /// leftmost view and each identity view.
  865. holder(const Type& v, const Allocator& alloc = Allocator())
  866. // Alas, cannot use an rvalue reference for 'v' because it is used
  867. // twice in the same expression for initializing imp.
  868. : imp(monoid_type(v, alloc), v) { }
  869. /// Construct from a functor that is used to initialize both the
  870. /// leftmost view and each identity view. The functor, 'f', must be be
  871. /// invokable using the expression 'Type x = f()'.
  872. template <typename Func>
  873. holder(const Func& f, const Allocator& alloc = Allocator())
  874. // Alas, cannot use an rvalue for 'f' because it is used twice in
  875. // the same expression for initializing imp.
  876. : imp(monoid_type(f, alloc), make_value(f)) { }
  877. };
  878. } // end namespace cilk
  879. #else /* C */
  880. # error Holders are currently available only for C++
  881. #endif /* __cplusplus */
  882. #endif /* HOLDER_H_INCLUDED */