MADNESS  version 0.9
worldobj.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 
31 
32  $Id$
33 */
34 
38 
39 #ifndef MADNESS_WORLD_WORLDOBJ_H__INCLUDED
40 #define MADNESS_WORLD_WORLDOBJ_H__INCLUDED
41 
44 
45 namespace madness {
46 
47  namespace detail {
48 
49  // Common base class for pending messages to ensure in-order processing
50 
51  // To eliminate synchronization when a distributed object is first
52  // constructed, we buffer pending messages for containers that
53  // don't have their id yet registered.
54  struct PendingMsg {
58 
59  PendingMsg(uniqueidT id, am_handlerT handler, const AmArg& arg)
60  : id(id), handler(handler), arg(copy_am_arg(arg)) {}
61 
62  void invokehandler() {
63  handler(*arg);
64  free_am_arg(arg);
65  };
66  };
67 
68  // It is annoying that we must replicate the task forwarding stuff here but we must
69  // so that pending messages creating tasks are correctly handled. Cannot merge
70  // easily with send handlers since task layer is more restrictive on the
71  // copy capability of arguments.
72 
73  // It is also annoying that info needs to be broken into two parts so
74  // that it id and ref are properly serialized. We need to have id
75  // correctly aligned via opaque_wrap, but ref cannot be serialized that
76  // way. Thus we break the class into two parts.
77 
78  // Info stored for AM method forwarding
79  template <typename memfunT>
80  struct info_base {
81  uniqueidT id; // Must be at front ... see peek.
83  memfunT memfun;
85 
86  protected:
87 
88  info_base() {}
89 
90  info_base(const uniqueidT& id, ProcessID requestor, memfunT memfun,
91  const TaskAttributes& attr=TaskAttributes())
92  : id(id)
93  , requestor(requestor)
94  , memfun(memfun)
95  , attr(attr) {}
96 
97 
98  template <typename Archive>
99  void serialize(const Archive& ar) {
100  ar & archive::wrap_opaque(*this); // Must be opaque ... see peek.
101  }
102  }; // struct info_base
103 
104  template <typename memfunT>
105  struct info : public info_base<memfunT> {
108  refT ref;
109 
110  info() : info_base<memfunT>() {}
111 
112  info(const AmArg& arg) :
113  info_base<memfunT>()
114  {
115  arg & *this;
116  }
117 
118  info(const uniqueidT& id, ProcessID requestor, memfunT memfun, const refT& ref,
119  const TaskAttributes& attr=TaskAttributes()) :
120  info_base<memfunT>(id, requestor, memfun, attr), ref(ref)
121  {}
122 
123  template <typename Archive>
124  void serialize(const Archive& ar) {
126  ar & ref;
127  }
128  }; // struct info
129 
130  // Extract the unique object ID from an incoming active message header
131 
132  // We deserialize the header and all arguments at the same
133  // time to simplify the code. However, it is common that
134  // when sending a message to an item in a container to
135  // include a pointer to the container itself. But this
136  // breaks if the container is not initialized since the
137  // deserialization throws if the object is not initialized
138  // (which seems preferable to hidden race condition). Hence,
139  // we use this routine to extract the unique ID from the very
140  // front of the info structure. For efficiency we here rely
141  // upon the serialization of info being opaque and the
142  // id being at the front of info.
143  static inline const uniqueidT& peek(const AmArg& arg) {
144  return *((uniqueidT*)(arg.buf()));
145  }
146  }
147 
148 
150 
166  template <class Derived>
167  class WorldObject {
168  typedef WorldObject<Derived> objT;
169  typedef std::list<detail::PendingMsg> pendingT;
170  public:
172  private:
173  // The order here matters in a multi-threaded world
174  volatile bool ready;
175  ProcessID me;
176  static Spinlock pending_mutex;
177 
178  static volatile pendingT pending;
179 
180  uniqueidT objid;
181 
182  typedef detail::voidT voidT;
183 
184  // This slightly convoluted logic is to ensure ordering when
185  // processing pending messages. If a new message arrives
186  // while processing incoming messages it must be queued.
187  //
188  // If the object does not exist ---> not ready
189  // If the object exists and is ready ---> ready
190  // If the object exists and is not ready then
191  // if we are doing a queued/pending message --> ready
192  // else this is a new message --> not ready
193  static bool is_ready(const uniqueidT& id, Derived*& obj, const AmArg& arg, am_handlerT ptr) {
194  obj = arg.get_world()-> template ptr_from_id<Derived>(id);
195 
196  if (obj) {
197  WorldObject* p = static_cast<WorldObject*>(obj);
198  if (p->ready || arg.is_pending()) return true;
199  }
200 
201  pending_mutex.lock(); // BEGIN CRITICAL SECTION
202  if (!obj) obj = arg.get_world()-> template ptr_from_id<Derived>(id);
203 
204  if (obj) {
205  WorldObject* p = static_cast<WorldObject*>(obj);
206  if (p->ready || arg.is_pending()) {
207  pending_mutex.unlock(); // ... LEAVE CRITICAL SECTION
208  return true;
209  }
210  }
211  const_cast<AmArg&>(arg).set_pending();
212  const_cast<pendingT&>(pending).push_back(detail::PendingMsg(id, ptr, arg));
213  pending_mutex.unlock(); // END CRITICAL SECTION
214 
215  return false;
216  }
217 
218  // Handler for incoming AM
219  template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T,
220  typename arg5T, typename arg6T, typename arg7T, typename arg8T, typename arg9T>
221  static void handler(const AmArg& arg) {
222  const uniqueidT& id = detail::peek(arg);
223  am_handlerT ptr = handler<memfunT,arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T,arg8T,arg9T>;
224  Derived* obj;
225  if (is_ready(id,obj,arg,ptr)) {
227  typename detail::task_arg<arg1T>::type arg1;
228  typename detail::task_arg<arg2T>::type arg2;
229  typename detail::task_arg<arg3T>::type arg3;
230  typename detail::task_arg<arg4T>::type arg4;
231  typename detail::task_arg<arg5T>::type arg5;
232  typename detail::task_arg<arg6T>::type arg6;
233  typename detail::task_arg<arg7T>::type arg7;
234  typename detail::task_arg<arg8T>::type arg8;
235  typename detail::task_arg<arg9T>::type arg9;
236  arg & info & arg1 & arg2 & arg3 & arg4 & arg5 & arg6 & arg7 & arg8 & arg9;
237  typename detail::info<memfunT>::futureT result(info.ref);
239  arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
240  }
241  }
242 
243  // Handler for remote arguments
244  template <typename taskT>
245  static void spawn_remote_task_handler(const AmArg& arg) {
246  MADNESS_ASSERT(taskT::arity <= 9u);
247 
248  const uniqueidT& id = detail::peek(arg);
249  am_handlerT ptr = & objT::template spawn_remote_task_handler<taskT>;
250  Derived* obj;
251  if (is_ready(id,obj,arg,ptr)) {
252  detail::info<typename taskT::functionT::memfn_type> info;
253 
254  archive::BufferInputArchive input_arch = arg & info;
255 
256  // Construct task
257  taskT* task = new taskT(typename taskT::futureT(info.ref),
258  detail::wrap_mem_fn(obj,info.memfun), info.attr, input_arch);
259 
260  // Add task to queue
261  arg.get_world()->taskq.add(task);
262  }
263  }
264 
265  template <typename T>
266  static inline const T& am_arg(const Future<T>& f) {
267  MADNESS_ASSERT(f.probe()); // Cannot serialize unassigned futures
268  return f.get();
269  }
270 
271  template <typename T> static inline const T& am_arg(const T& t) { return t; }
272 
273  template <typename memfnT, typename a1T, typename a2T, typename a3T,
274  typename a4T, typename a5T, typename a6T, typename a7T,
275  typename a8T, typename a9T>
276  typename detail::task_result_type<memfnT>::futureT
277  send_am(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
278  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
279  const a7T& a7, const a8T& a8, const a9T& a9) const
280  {
281  typename detail::task_result_type<memfnT>::futureT result;
282  if (dest == me)
283  detail::run_function(result, detail::wrap_mem_fn(get_derived<memfnT>(), memfn),
284  a1, a2, a3, a4, a5, a6, a7, a8, a9);
285  else {
286  detail::info<memfnT> info(objid, me, memfn, result.remote_ref(world));
287  world.am.send(dest, & objT::template handler<memfnT, a1T, a2T, a3T, a4T, a5T, a6T, a7T, a8T, a9T>,
288  new_am_arg(info, a1, a2, a3, a4, a5, a6, a7, a8, a9));
289  }
290 
291  return result;
292  }
293 
294  template <typename taskT, typename memfnT, typename a1T, typename a2T, typename a3T,
295  typename a4T, typename a5T, typename a6T, typename a7T,
296  typename a8T, typename a9T>
297  typename taskT::futureT
298  send_task(ProcessID dest, memfnT memfn, const a1T& a1,
299  const a2T& a2, const a3T& a3, const a4T& a4, const a5T& a5,
300  const a6T& a6, const a7T& a7, const a8T& a8, const a9T& a9,
301  const TaskAttributes& attr) const
302  {
303  typename taskT::futureT result;
304  detail::info<memfnT> info(objid, me, memfn, result.remote_ref(world), attr);
305  world.am.send(dest, & objT::template spawn_remote_task_handler<taskT>,
306  new_am_arg(info, a1, a2, a3, a4, a5, a6, a7, a8, a9));
307 
308  return result;
309  }
310 
311  template <typename memfnT>
312  typename enable_if_c<detail::memfunc_traits<memfnT>::constness, const Derived*>::type
313  get_derived() const { return static_cast<const Derived*>(this); }
314 
315 
316  template <typename memfnT>
317  typename disable_if_c<detail::memfunc_traits<memfnT>::constness, Derived*>::type
318  get_derived() const { return const_cast<Derived*>(static_cast<const Derived*>(this)); }
319 
320  protected:
321 
323 
331  // Messages may be arriving while we are processing the
332  // pending queue. To maximize concurrency copy messages
333  // out of queue before processing outside critical section.
334  //int ndone = 0;
335  while (!ready) {
336  pendingT tmp;
337 
338  pending_mutex.lock(); // BEGIN CRITICAL SECTION
339  pendingT& nv = const_cast<pendingT&>(pending);
340  for (pendingT::iterator it=nv.begin(); it!=nv.end();) {
341  detail::PendingMsg& p = *it;
342  if (p.id == objid) {
343  tmp.push_back(p);
344  it = nv.erase(it);
345  }
346  else {
347  ++it;
348  }
349  }
350  if (tmp.size() == 0) ready=true;
351  pending_mutex.unlock(); // END CRITICAL SECTION
352 
353  while (tmp.size()) {
354  tmp.front().invokehandler();
355  tmp.pop_front();
356  //++ndone;
357  }
358  }
359  //if (ndone) std::cout << world.rank() << ":pending:" << ndone << std::endl;
360  }
361 
362 
363  public:
365 
370  : world(world)
371  , ready(false)
372  , me(world.rank())
373  , objid(world.register_ptr(static_cast<Derived*>(this))) {};
374 
375 
377  const uniqueidT& id() const {
378  return objid;
379  }
380 
382  World& get_world() const {
383  return const_cast<WorldObject<Derived>*>(this)->world;
384  }
385 
386  template <typename memfnT>
388  send(ProcessID dest, memfnT memfn) const {
389  return send_am(dest, memfn, voidT::value, voidT::value, voidT::value,
392  }
393 
394  template <typename memfnT, typename a1T>
396  send(ProcessID dest, memfnT memfn, const a1T& a1) const {
397  return send_am(dest, memfn, am_arg(a1), voidT::value, voidT::value,
400  }
401 
402  template <typename memfnT, typename a1T, typename a2T>
404  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2) const {
405  return send_am(dest, memfn, am_arg(a1), am_arg(a2), voidT::value,
408  }
409 
410  template <typename memfnT, typename a1T, typename a2T, typename a3T>
412  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
413  const a3T& a3) const
414  {
415  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
418  }
419 
420  template <typename memfnT, typename a1T, typename a2T, typename a3T,
421  typename a4T>
423  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
424  const a3T& a3, const a4T& a4) const
425  {
426  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
427  am_arg(a4), voidT::value, voidT::value, voidT::value,
429  }
430 
431  template <typename memfnT, typename a1T, typename a2T, typename a3T,
432  typename a4T, typename a5T>
434  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
435  const a3T& a3, const a4T& a4, const a5T& a5) const
436  {
437  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
438  am_arg(a4), am_arg(a5), voidT::value, voidT::value,
440  }
441 
442  template <typename memfnT, typename a1T, typename a2T, typename a3T,
443  typename a4T, typename a5T, typename a6T>
445  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
446  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6) const
447  {
448  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
449  am_arg(a4), am_arg(a5), am_arg(a6), voidT::value, voidT::value,
450  voidT::value);
451  }
452 
453  template <typename memfnT, typename a1T, typename a2T, typename a3T,
454  typename a4T, typename a5T, typename a6T, typename a7T>
456  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
457  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
458  const a7T& a7) const
459  {
460  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
461  am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), voidT::value,
462  voidT::value);
463  }
464 
465  template <typename memfnT, typename a1T, typename a2T, typename a3T,
466  typename a4T, typename a5T, typename a6T, typename a7T, typename a8T>
468  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
469  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
470  const a7T& a7, const a8T& a8) const
471  {
472  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
473  am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), am_arg(a8),
474  voidT::value);
475  }
476 
477  template <typename memfnT, typename a1T, typename a2T, typename a3T,
478  typename a4T, typename a5T, typename a6T, typename a7T, typename a8T,
479  typename a9T>
481  send(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
482  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
483  const a7T& a7, const a8T& a8, const a9T& a9) const
484  {
485  return send_am(dest, memfn, am_arg(a1), am_arg(a2), am_arg(a3),
486  am_arg(a4), am_arg(a5), am_arg(a6), am_arg(a7), am_arg(a8),
487  am_arg(a9));
488  }
489 
491  template <typename memfnT>
493  task(ProcessID dest, memfnT memfn, const TaskAttributes& attr = TaskAttributes()) const {
495  typedef TaskFn<fnT> taskT;
496  if (dest == me)
497  return world.taskq.add(get_derived<memfnT>(), memfn, attr);
498  else
499  return send_task<taskT>(dest, memfn, voidT::value, voidT::value,
502  }
503 
505  template <typename memfnT, typename a1T>
507  task(ProcessID dest, memfnT memfn, const a1T& a1,
508  const TaskAttributes& attr = TaskAttributes()) const
509  {
512  if (dest == me)
513  return world.taskq.add(get_derived<memfnT>(), memfn, a1, attr);
514  else
515  return send_task<taskT>(dest, memfn, am_arg(a1), voidT::value,
518  }
519 
521  template <typename memfnT, typename a1T, typename a2T>
523  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
524  const TaskAttributes& attr = TaskAttributes()) const
525  {
528  typename detail::task_arg<a2T>::type> taskT;
529  if (dest == me)
530  return world.taskq.add(get_derived<memfnT>(), memfn, a1, a2, attr);
531  else
532  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
535  }
536 
538  template <typename memfnT, typename a1T, typename a2T, typename a3T>
540  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
541  const a3T& a3, const TaskAttributes& attr = TaskAttributes()) const
542  {
546  typename detail::task_arg<a3T>::type> taskT;
547  if (dest == me)
548  return world.taskq.add(get_derived<memfnT>(), memfn, a1, a2, a3, attr);
549  else
550  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
551  am_arg(a3), voidT::value, voidT::value, voidT::value,
553  }
554 
556  template <typename memfnT, typename a1T, typename a2T, typename a3T,
557  typename a4T>
559  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
560  const a3T& a3, const a4T& a4, const TaskAttributes& attr = TaskAttributes()) const
561  {
566  typename detail::task_arg<a4T>::type> taskT;
567  if (dest == me)
568  return world.taskq.add(get_derived<memfnT>(), memfn, a1, a2, a3, a4, attr);
569  else
570  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
571  am_arg(a3), am_arg(a4), voidT::value, voidT::value,
573  }
574 
576  template <typename memfnT, typename a1T, typename a2T, typename a3T,
577  typename a4T, typename a5T>
579  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
580  const a3T& a3, const a4T& a4, const a5T& a5,
581  const TaskAttributes& attr = TaskAttributes()) const
582  {
588  typename detail::task_arg<a5T>::type> taskT;
589  if (dest == me)
590  return world.taskq.add(get_derived<memfnT>(), memfn, a1, a2, a3, a4, a5, attr);
591  else
592  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
593  am_arg(a3), am_arg(a4), am_arg(a5), voidT::value,
595  }
596 
598  template <typename memfnT, typename a1T, typename a2T, typename a3T,
599  typename a4T, typename a5T, typename a6T>
601  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
602  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
603  const TaskAttributes& attr = TaskAttributes()) const
604  {
611  typename detail::task_arg<a6T>::type> taskT;
612  if (dest == me)
613  return world.taskq.add(get_derived<memfnT>(), memfn, a1, a2, a3, a4, a5, a6, attr);
614  else {
615  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
616  am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
618  }
619  }
620 
622  template <typename memfnT, typename a1T, typename a2T, typename a3T,
623  typename a4T, typename a5T, typename a6T, typename a7T>
625  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
626  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
627  const a7T& a7, const TaskAttributes& attr = TaskAttributes()) const
628  {
636  typename detail::task_arg<a7T>::type> taskT;
637  if (dest == me)
638  return world.taskq.add(get_derived<memfnT>(), memfn, a1, a2, a3, a4, a5, a6, a7, attr);
639  else
640  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
641  am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
642  am_arg(a7), voidT::value, voidT::value, attr);
643  }
644 
646  template <typename memfnT, typename a1T, typename a2T, typename a3T,
647  typename a4T, typename a5T, typename a6T, typename a7T, typename a8T>
649  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
650  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
651  const a7T& a7, const a8T& a8,
652  const TaskAttributes& attr = TaskAttributes()) const
653  {
662  typename detail::task_arg<a8T>::type> taskT;
663  if (dest == me)
664  return world.taskq.add(get_derived<memfnT>(), memfn, a1, a2, a3, a4, a5, a6, a7, a8, attr);
665  else {
666  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
667  am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
668  am_arg(a7), am_arg(a8), voidT::value, attr);
669  }
670  }
671 
673  template <typename memfnT, typename a1T, typename a2T, typename a3T,
674  typename a4T, typename a5T, typename a6T, typename a7T, typename a8T,
675  typename a9T>
677  task(ProcessID dest, memfnT memfn, const a1T& a1, const a2T& a2,
678  const a3T& a3, const a4T& a4, const a5T& a5, const a6T& a6,
679  const a7T& a7, const a8T& a8, const a9T& a9,
680  const TaskAttributes& attr = TaskAttributes()) const
681  {
691  typename detail::task_arg<a9T>::type> taskT;
692  if (dest == me)
693  return world.taskq.add(get_derived<memfnT>(), memfn, a1, a2, a3, a4, a5, a6, a7, a8, a9, attr);
694  else
695  return send_task<taskT>(dest, memfn, am_arg(a1), am_arg(a2),
696  am_arg(a3), am_arg(a4), am_arg(a5), am_arg(a6),
697  am_arg(a7), am_arg(a8), am_arg(a9), attr);
698  }
699 
700  virtual ~WorldObject() {
701  if(initialized())
702  world.unregister_ptr(static_cast<Derived*>(this));
703  }
704  };
705 
706  namespace archive {
707  template <class Derived>
709  static inline void load(const BufferInputArchive& ar, WorldObject<Derived>*& ptr) {
710  uniqueidT id;
711  ar & id;
712  World* world = World::world_from_id(id.get_world_id());
713  MADNESS_ASSERT(world);
714  ptr = world->ptr_from_id< WorldObject<Derived> >(id);
715  if (!ptr) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally uninitialized object",0);
716  }
717  };
718 
719  template <class Derived>
721  static inline void store(const BufferOutputArchive& ar, WorldObject<Derived>* const& ptr) {
722  ar & ptr->id();
723  }
724  };
725 
726  template <class Derived>
728  static inline void load(const BufferInputArchive& ar, const WorldObject<Derived>*& ptr) {
729  uniqueidT id;
730  ar & id;
731  World* world = World::world_from_id(id.get_world_id());
732  MADNESS_ASSERT(world);
733  ptr = world->ptr_from_id< WorldObject<Derived> >(id);
734  if (!ptr) MADNESS_EXCEPTION("WorldObj: remote operation attempting to use a locally uninitialized object",0);
735  }
736  };
737 
738  template <class Derived>
740  static inline void store(const BufferOutputArchive& ar, const WorldObject<Derived>* const& ptr) {
741  ar & ptr->id();
742  }
743  };
744  }
745 }
746 
747 #ifdef WORLD_INSTANTIATE_STATIC_TEMPLATES
748 template <typename Derived>
749 volatile std::list<madness::detail::PendingMsg> madness::WorldObject<Derived>::pending;
750 
752 
753 #endif
754 
755 #endif // MADNESS_WORLD_WORLDOBJ_H__INCLUDED
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4) const
Definition: worldobj.h:423
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8)".
Definition: worldobj.h:649
void free_am_arg(AmArg *arg)
Frees an AmArg allocated with alloc_am_arg.
Definition: worldam.h:178
World * get_world() const
For incoming AM gives the associated world.
Definition: worldam.h:155
void process_pending()
To be called from derived constructor to process pending messages.
Definition: worldobj.h:330
void(* am_handlerT)(const AmArg &)
Type of AM handler functions.
Definition: worldam.h:78
World active message that extends an RMI message.
Definition: worldam.h:81
World & get_world() const
Returns a reference to the world.
Definition: worldobj.h:382
RemoteReference< FutureImpl< REMFUTURE(MEMFUN_RETURNT(memfunT)) > > refT
Definition: worldobj.h:107
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6) const
Definition: worldobj.h:445
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1)".
Definition: worldobj.h:507
static void store(const BufferOutputArchive &ar, const WorldObject< Derived > *const &ptr)
Definition: worldobj.h:740
AmArg * arg
Definition: worldobj.h:57
PendingMsg(uniqueidT id, am_handlerT handler, const AmArg &arg)
Definition: worldobj.h:59
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2,a3)".
Definition: worldobj.h:540
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7) const
Definition: worldobj.h:456
AmArg * new_am_arg(const A &a, const B &b, const C &c, const D &d, const E &e, const F &f, const G &g, const H &h, const I &i, const J &j)
Convenience template for serializing arguments into a new AmArg.
Definition: worldam.h:185
Definition: worldobj.h:54
Definition: uniqueid.h:46
void unlock() const
Free a spinlock owned by this thread.
Definition: worldmutex.h:230
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn) const
Definition: worldobj.h:388
Specialization of Future for internal convenience ... does nothing useful!
Definition: worldfut.h:598
static void store(const BufferOutputArchive &ar, WorldObject< Derived > *const &ptr)
Definition: worldobj.h:721
void lock() const
Acquire the spinlock waiting if necessary.
Definition: worldmutex.h:224
info(const uniqueidT &id, ProcessID requestor, memfunT memfun, const refT &ref, const TaskAttributes &attr=TaskAttributes())
Definition: worldobj.h:118
const uniqueidT & id() const
Returns the globally unique object ID.
Definition: worldobj.h:377
NDIM & f
Definition: mra.h:2179
Definition: worldobj.h:105
Default store of a thingy via serialize(ar,t)
Definition: archive.h:708
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3) const
Definition: worldobj.h:412
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only) ...
Definition: tensor.h:2429
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1) const
Definition: worldobj.h:396
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8) const
Definition: worldobj.h:468
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2,a3,a4,a5,a6)".
Definition: worldobj.h:601
static World * world_from_id(unsigned long id)
Convert world id to world pointer.
Definition: worldfwd.h:628
WorldAmInterface & am
AM interface.
Definition: worldfwd.h:460
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5) const
Definition: worldobj.h:434
T type
Definition: taskfn.h:191
am_handlerT handler
Definition: worldobj.h:56
Future< REMFUTURE(MEMFUN_RETURNT(memfunT)) > futureT
Definition: worldobj.h:106
Wraps an archive around a memory buffer for output.
Definition: bufar.h:58
void serialize(const Archive &ar)
Definition: worldobj.h:124
const double a2
Definition: vnucso.cc:91
info_base(const uniqueidT &id, ProcessID requestor, memfunT memfun, const TaskAttributes &attr=TaskAttributes())
Definition: worldobj.h:90
memfunT memfun
Definition: worldobj.h:83
Simple structure used to manage references/pointers to remote instances.
Definition: worldref.h:59
refT ref
Definition: worldobj.h:108
enable_if< std::is_void< typename detail::result_of< fnT >::type > >::type run_function(Future< void > &result, fnT fn, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &, const voidT &)
Definition: taskfn.h:233
info_base()
Definition: worldobj.h:88
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2,a3,a4,a5)".
Definition: worldobj.h:579
const T1 &f1 return GTEST_2_TUPLE_() T(f0, f1)
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8,a9)".
Definition: worldobj.h:493
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8, const a9T &a9, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7,a8,a9)".
Definition: worldobj.h:677
ProcessID requestor
Definition: worldobj.h:82
MemFuncWrapper< objT *, memfnT, typename result_of< memfnT >::type > wrap_mem_fn(objT &obj, memfnT memfn)
Definition: worldtask.h:358
Implements Dqueue, Thread, ThreadBase and ThreadPool.
Default load of a thingy via serialize(ar,t)
Definition: archive.h:718
uniqueidT id
Definition: worldobj.h:81
static void load(const BufferInputArchive &ar, WorldObject< Derived > *&ptr)
Definition: worldobj.h:709
static void load(const BufferInputArchive &ar, const WorldObject< Derived > *&ptr)
Definition: worldobj.h:728
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2) const
Definition: worldobj.h:404
void unregister_ptr(T *ptr)
Unregister a unique id for a local pointer.
Definition: worldfwd.h:575
bool initialized()
Definition: world.cc:70
uniqueidT id
Definition: worldobj.h:55
RMI::Request send(const ProcessID dest, am_handlerT op, const AmArg *arg, const int attr=RMI::ATTR_ORDERED, const bool managed=true)
Sends an unmanaged non-blocking active message.
Definition: worldam.h:386
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2,a3,a4,a5,a6,a7)".
Definition: worldobj.h:625
Implements most parts of a globally addressable object (via unique ID)
Definition: worldam.h:74
A parallel world with full functionality wrapping an MPI communicator.
Definition: worldfwd.h:416
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2)".
Definition: worldobj.h:523
int ProcessID
Used to clearly identify process number/rank.
Definition: worldtypes.h:37
Wrap a callable object and its arguments into a task function.
Definition: taskfn.h:388
Definition: worldobj.h:80
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method "returnT (this->*memfn)(a1,a2,a3,a4)".
Definition: worldobj.h:559
archive_array< unsigned char > wrap_opaque(const T *, unsigned int)
Factory function to wrap pointer to contiguous data as opaque (uchar) archive_array.
Definition: archive.h:827
Wraps an archive around a memory buffer for input.
Definition: bufar.h:206
void add(TaskInterface *t)
Add a new local task taking ownership of the pointer.
Definition: worldtask.h:473
TaskAttributes attr
Definition: worldobj.h:84
WorldTaskQueue & taskq
Task queue.
Definition: worldfwd.h:461
Contains attributes of a task.
Definition: worldthread.h:208
const double a1
Definition: vnucso.cc:90
void serialize(const Archive &ar)
Definition: worldobj.h:99
static const Future< void > value
Definition: worldfut.h:602
WorldObject(World &world)
Associates object with globally unique ID.
Definition: worldobj.h:369
Definition: taskfn.h:50
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn, const a1T &a1, const a2T &a2, const a3T &a3, const a4T &a4, const a5T &a5, const a6T &a6, const a7T &a7, const a8T &a8, const a9T &a9) const
Definition: worldobj.h:481
Defines TaskInterface and implements WorldTaskQueue and associated stuff.
T * ptr_from_id(uniqueidT id) const
Look up local pointer from world-wide unique id.
Definition: worldfwd.h:597
info(const AmArg &arg)
Definition: worldobj.h:112
A future is a possibly yet unevaluated value.
Definition: ref.h:210
AmArg * copy_am_arg(const AmArg &arg)
Definition: worldam.h:171
virtual ~WorldObject()
Definition: worldobj.h:700
#define MADNESS_EXCEPTION(msg, value)
Definition: worldexc.h:88
Spinlock using pthread spinlock operations.
Definition: worldmutex.h:200
info()
Definition: worldobj.h:110
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
void invokehandler()
Definition: worldobj.h:62
unsigned char * buf() const
Returns a pointer to the user's payload (aligned in same way as AmArg)
Definition: worldam.h:133
World & world
Think globally act locally.
Definition: worldobj.h:171