VR-Forces Development_Version Class Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
featureSetWrappers.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright (c) 2015 MAK Technologies, Inc.
3  * All rights reserved.
4  ******************************************************************************/
5 
9 
10 #pragma once
11 
12 #include <features/featureSet.h>
14 
15 #include <vrfutil/objectCounter.h>
16 
17 #include <boost/scoped_ptr.hpp>
18 #include <boost/shared_ptr.hpp>
19 #include <boost/weak_ptr.hpp>
20 #include <boost/foreach.hpp>
21 #include <boost/signals2.hpp>
22 
23 #include <tbb/spin_mutex.h>
24 #include <tbb/spin_rw_mutex.h>
25 #include <tbb/null_rw_mutex.h>
26 
29 
32 
35 
36 namespace MAKVRinTerra
37 {
39  template <
40  typename Derived,
41  typename FS,
42  typename Inner = FS>
43  class DtFeatureSetWrapperTemplate : public FS
44  {
45  protected:
46  Derived* This() { return static_cast<Derived*>(this); }
47  const Derived* This() const { return static_cast<const Derived*>(this); }
48 
51  {
52  }
53 
54  public:
55  typedef FS FeatureSet;
56  typedef typename FeatureSet::Feature Feature;
57  typedef typename FeatureSet::ForEachFunction ForEachFunction;
58  typedef typename FeatureSet::DetachCallback DetachCallback;
59  typedef typename FeatureSet::LoadedCallback LoadedCallback;
60 
61  typedef boost::shared_ptr<Inner> Ptr;
62  typedef boost::shared_ptr<const Inner> CPtr;
63 
64  template <typename Function=ForEachFunction>
65  class CallbackRecord;
66 
67  std::string label() const
68  {
69  CPtr handle(This()->getPtr());
70  if (handle)
71  return handle->label();
72 
73  return "empty feature set wrapper";
74  }
75 
76 
77  unsigned numberOfFeatures() const
78  {
79  CPtr handle(This()->getPtr());
80  if (handle)
81  return handle->numberOfFeatures();
82 
83  return 0;
84  }
85 
86  bool elided() const
87  {
88  CPtr handle(This()->getPtr());
89  if (handle)
90  return handle->elided();
91 
92  return FS::elided();
93  }
94 
95  bool empty() const
96  {
97  CPtr handle(This()->getPtr());
98  if (handle)
99  return handle->empty();
100 
101  return FS::empty();
102  }
103 
104  bool isIndexed() const
105  {
106  CPtr handle(This()->getPtr());
107  if (handle)
108  return handle->isIndexed();
109 
110  return FS::isIndexed();
111  }
112 
113  bool loaded(double timeout=0.0) const
114  {
115  CPtr handle(This()->getPtr());
116  if (handle)
117  return handle->loaded(timeout);
118 
119  return false;
120  }
121 
122  virtual bool loadedThrowIfNotSet(double timeout=0.0) const
123  {
124  CPtr handle(This()->getPtr());
125  if (handle)
126  return handle->loaded(timeout);
127 
129  }
130 
132  : public DtObjectDebugger<LoadedCounter>
133  {
135  explicit LoadedCounter(const LoadedCallback& cb) : callback(cb) { }
136  void operator()() const { callback(); }
137  };
138 
140  {
141  if (!cb)
142  DetachCallback();
143 
144  //boost::signals2::connection conn = myLoadedSignal->connect(cb);
145  boost::signals2::connection conn = myLoadedSignal->connect(LoadedCounter(cb));
146 
147  try
148  {
149  return boost::bind(&boost::signals2::connection::disconnect, conn);
150  }
151  catch (...)
152  {
153  conn.disconnect();
154  throw;
155  }
156  }
157 
158  void forEachFeatureParallel(const ForEachFunction& func) const
159  {
160  CPtr handle(This()->getPtr());
161  if (handle)
162  handle->forEachFeatureParallel(func);
163  }
164 
166  {
167  typedef CallbackRecord<ForEachFunction> Record;
168  typedef typename Record::Ptr RecordPtr;
169 
170  DetachCallback detacher;
171 
173  CPtr handle(This()->getPtr());
174  if (handle)
175  detacher = handle->forEachFeatureAsync(func);
176 
178  try
179  {
180  typename CallbackMutex::scoped_lock headLock(myCallbackMutex);
181  RecordPtr newHead(Record::Make(func, myHead, detacher));
182  const_cast<RecordPtr&>(myHead) = newHead;
183  return typename Record::Detacher(newHead);
184  }
185  catch (...)
186  {
187  if (detacher)
188  detacher();
189 
190  throw;
191  }
192  }
193 
195  const DtQuery& query,
196  const boost::optional<DtFeatureGeometry>& geometry,
197  DtLoadType load) const
198  {
199  CPtr handle(This()->getPtr());
200  if (handle)
201  return Wrap(handle->filter(query, geometry, load));
202 
204  assert(false);
205  DtTHROW_NEW(DtException, "filtered empty feature set wrapper");
206  }
207 
208  FeatureSet* filter(const DtQuery& query, DtLoadType load) const
209  {
210  return FS::filter(query, load);
211  }
212 
213  FeatureSet* filter(const boost::optional<DtFeatureGeometry>& geometry, DtLoadType load) const
214  {
215  return FS::filter(geometry, load);
216  }
217 
218  public:
219  template <typename Function>
221  : public DtObjectDebugger<DtFeatureSetWrapperCallbackRecordTag>
222  {
223  public:
224  typedef boost::shared_ptr<CallbackRecord> Ptr;
225  typedef boost::weak_ptr<CallbackRecord> WPtr;
226 
227  struct Detacher
228  : public DtObjectDebugger<DtFeatureSetWrapperCallbackRecordDetacherTag>
229  {
230  void operator()() const
231  {
232  boost::shared_ptr<CallbackRecord> callback(callbackWptr.lock());
233  if (callback)
234  callback->detach();
235  }
236 
237  explicit Detacher(const boost::shared_ptr<CallbackRecord>& rec)
238  : callbackWptr(rec) { }
239 
240  boost::weak_ptr<CallbackRecord> callbackWptr;
241  };
242 
243  static Ptr Make(const Function& func, const Ptr& curHead, const DetachCallback& detach)
244  {
245  Ptr newRec(new CallbackRecord(func, curHead, detach));
246  while (newRec->next)
247  {
248  Mutex::scoped_lock lock(newRec->next->mutex);
249  if (newRec->next->func)
250  break;
251 
252  newRec->next = newRec->next->next;
253  }
254 
255  return newRec;
256  }
257 
260  void addCallbacksTo(const CPtr& fs)
261  {
262  Mutex::scoped_lock lock(mutex);
263 
266  if (detacher)
267  {
268  detacher();
270  }
271 
273  if (func && fs)
274  {
275  Function f(func);
276 
277  lock.release();
278  DetachCallback d = fs->forEachFeatureAsync(f);
279  lock.acquire(mutex);
280 
281  if (func)
282  detacher = d;
283  else if (d)
284  d();
285  }
286 
287  Ptr ne = next;
288  lock.release();
289 
290  if (ne)
291  {
292  try
293  {
294  ne->addCallbacksTo(fs);
295  }
296  catch (...)
297  {
298  lock.acquire(mutex);
299  if (detacher)
300  {
301  detacher();
303  }
304 
305  throw;
306  }
307  }
308  }
309 
310  void detach()
311  {
312  Mutex::scoped_lock lock(mutex);
313 
314  if (!func)
315  return;
316 
317  func = Function();
318 
319  if (detacher)
320  {
321  detacher();
323  }
324 
325  Ptr pr = prev.lock();
326  Ptr ne = next;
327 
328  while (pr)
329  {
330  lock.release();
331  lock.acquire(pr->mutex);
332 
333  if (pr->func)
334  break;
335 
336  pr = pr->prev.lock();
337  }
338 
339  while (ne)
340  {
341  Mutex::scoped_lock endLock(ne->mutex);
342  if (ne->func)
343  {
344  if (pr)
345  pr->next = ne;
346 
347  return;
348  }
349 
350  ne = ne->next;
351  }
352 
353  if (pr)
354  pr->next = ne;
355  }
356 
358  {
359  if (detacher)
360  detacher();
361  }
362 
363  typedef tbb::spin_mutex Mutex;
364 
365  private:
366  explicit CallbackRecord(
367  const Function& func,
368  const Ptr& next,
369  const DetachCallback& detach)
370  : func(func)
371  , next(next)
372  , detacher(detach)
373  {
374  }
375 
376  mutable Mutex mutex;
377  Function func;
381  };
382 
383 protected:
384  void setupCallbacks(const CPtr& fs)
385  {
386  typename CallbackMutex::scoped_lock lock(myCallbackMutex);
387 
388  myLoadedSignalDetacher.reset();
389 
390  if (myHead)
391  myHead->addCallbacksTo(fs);
392 
393  if (fs)
394  {
395  myLoadedSignalDetacher.reset(fs->addLoadedCallback(LoadedCaller(myLoadedSignal)));
396 
397  try
398  {
399  if (fs->loaded(0.0))
400  (*myLoadedSignal)();
401  }
402  catch (DtFeatureSetLoadingException&) { }
403  }
404  }
405 
406  private:
407  typedef tbb::spin_mutex CallbackMutex;
408  typedef boost::signals2::signal_type<
409  void (),
410  boost::signals2::keywords::mutex_type<tbb::spin_mutex> >::type LoadedSignal;
411 
412  struct LoadedCaller : public DtObjectDebugger<DtFeatureSetWrapperLoadedCallerTag>
413  {
414  boost::weak_ptr<LoadedSignal> sig;
415  explicit LoadedCaller(const boost::shared_ptr<LoadedSignal>& sig)
416  : sig(sig) { }
417 
418  void operator()() const
419  {
420  boost::shared_ptr<LoadedSignal> signal(sig.lock());
421  if (signal)
422  (*signal)();
423  }
424  };
425 
427  typename CallbackRecord<>::Ptr myHead;
428  boost::shared_ptr<LoadedSignal> myLoadedSignal;
429  typename FeatureSet::DetachScopeGuard myLoadedSignalDetacher;
430  };
431 
432  template <
433  typename FS,
434  template <typename> class PtrTemplate,
435  typename Inner>
436  class DtFeatureSetWrapper;
437 
438  template <typename FS, typename Inner>
439  class DtFeatureSetWrapper<FS,boost::scoped_ptr,Inner> : public FS
440  {
441  public:
442  typedef typename FS::Feature Feature;
443  typedef typename FS::ForEachFunction ForEachFunction;
444  typedef typename FS::LoadedCallback LoadedCallback;
445  typedef typename FS::DetachCallback DetachCallback;
446 
447  explicit DtFeatureSetWrapper(Inner* fs) : mySet(fs)
448  {
449  assert(mySet);
450  }
451 
452  template <typename OtherFS>
453  explicit DtFeatureSetWrapper(std::auto_ptr<OtherFS> fs)
454  : mySet(fs.release())
455  {
456  assert(mySet);
457  }
458 
459  Inner* getPtr() { return mySet.get(); }
460  const Inner* getPtr() const { return mySet.get(); }
461 
462  std::string label() const
463  {
464  return mySet->label();
465  }
466 
467  unsigned numberOfFeatures() const
468  {
469  return mySet->numberOfFeatures();
470  }
471 
472  bool elided() const
473  {
474  return mySet->elided();
475  }
476 
477  bool empty() const
478  {
479  return mySet->empty();
480  }
481 
482  bool isIndexed() const
483  {
484  return mySet->isIndexed();
485  }
486 
487  bool loaded(double timeout=0.0) const
488  {
489  return mySet->loaded(timeout);
490  }
491 
492  DetachCallback addLoadedCallback(const LoadedCallback& cb) const
493  {
494  return mySet->addLoadedCallback(cb);
495  }
496 
497  void forEachFeatureParallel(const ForEachFunction& func) const
498  {
499  mySet->forEachFeatureParallel(func);
500  }
501 
502  DetachCallback forEachFeatureAsync(const ForEachFunction& func) const
503  {
504  return mySet->forEachFeatureAsync(func);
505  }
506 
507  FS* filter(
508  const DtQuery& query,
509  const boost::optional<DtFeatureGeometry>& geometry,
510  DtLoadType load) const
511  {
512  return Wrap(mySet->filter(query, geometry, load));
513  }
514 
515  FS* clone() const
516  {
517  return Wrap(mySet->clone());
518  }
519 
520  private:
521  const boost::scoped_ptr<Inner> mySet;
522  };
523 
524  template <typename FS, typename Inner>
525  class DtFeatureSetWrapper<FS,boost::shared_ptr,Inner>
527  DtFeatureSetWrapper<FS,boost::shared_ptr,Inner>,
528  FS,
529  Inner>
530  {
531  public:
533  {
534  }
535 
536  explicit DtFeatureSetWrapper(Inner* fs)
537  {
538  assert(fs);
539  setPtr(boost::shared_ptr<Inner>(fs));
540  }
541 
542  template <typename OtherFS>
543  explicit DtFeatureSetWrapper(std::auto_ptr<OtherFS> fs)
544  {
545  assert(fs.get());
546  setPtr(boost::shared_ptr<Inner>(fs.release()));
547  }
548 
549  template <typename OtherFS>
550  explicit DtFeatureSetWrapper(const boost::shared_ptr<OtherFS>& fs)
551  {
552  assert(fs.get());
553  setPtr(fs);
554  }
555 
556  boost::shared_ptr<Inner> getPtr()
557  {
558  Mutex::scoped_lock lock(myMutex, false);
559  return mySet;
560  }
561 
562  boost::shared_ptr<const Inner> getPtr() const
563  {
564  Mutex::scoped_lock lock(myMutex, false);
565  return mySet;
566  }
567 
568  boost::shared_ptr<Inner> setPtr(const boost::shared_ptr<Inner>& p)
569  {
570  Mutex::scoped_lock lock(myMutex, false);
571  if (mySet && p)
572  return mySet;
573 
574  if (!lock.upgrade_to_writer() && mySet && p)
575  return mySet;
576 
577  mySet = p;
578 
579  lock.downgrade_to_reader();
580  this->setupCallbacks(p);
581 
582  return mySet;
583  }
584 
585  boost::shared_ptr<Inner> setPtr(Inner* set)
586  {
587  boost::shared_ptr<Inner> fs(set);
588  return setPtr(fs);
589  }
590 
591  FS* clone() const
592  {
593  return Wrap(getPtr());
594  }
595 
596  protected:
597  typedef tbb::spin_rw_mutex Mutex;
598  mutable Mutex myMutex;
599 
600  boost::shared_ptr<Inner> mySet;
601  };
602 
603  template <typename FS, typename Inner>
604  class DtFeatureSetWrapper<FS,boost::weak_ptr,Inner>
606  DtFeatureSetWrapper<FS,boost::weak_ptr,Inner>,
607  FS,
608  Inner>
609  {
610  public:
611  typedef typename FS::Feature Feature;
612  typedef typename FS::ForEachFunction ForEachFunction;
613  typedef typename FS::DetachCallback DetachCallback;
614 
616  : mySet() { }
617 
618  template <typename T>
619  explicit DtFeatureSetWrapper(const boost::weak_ptr<T>& fs)
620  {
621  setPtr(fs.lock());
622  }
623 
624  template <typename T>
625  explicit DtFeatureSetWrapper(const boost::shared_ptr<T>& fs)
626  {
627  assert(fs);
628  setPtr(fs);
629  }
630 
631  boost::shared_ptr<Inner> getPtr()
632  {
633  Mutex::scoped_lock lock(myMutex, false);
634  return mySet.lock();
635  }
636 
637  boost::shared_ptr<const Inner> getPtr() const
638  {
639  Mutex::scoped_lock lock(myMutex, false);
640  return mySet.lock();
641  }
642 
643  boost::shared_ptr<Inner> getMutablePtr() const
644  {
645  return const_cast<DtFeatureSetWrapper*>(this)->getPtr();
646  }
647 
648  boost::shared_ptr<Inner> setPtr(const boost::shared_ptr<Inner>& p)
649  {
650  Mutex::scoped_lock lock(myMutex, false);
651  if (p)
652  {
653  boost::shared_ptr<Inner> s(mySet.lock());
654  if (s)
655  return s;
656  }
657 
658  if (!lock.upgrade_to_writer() && p)
659  {
660  boost::shared_ptr<Inner> s(mySet.lock());
661  if (s)
662  return s;
663  }
664 
665  mySet = p;
666 
667  lock.downgrade_to_reader();
668  this->setupCallbacks(p);
669 
670  return p;
671  }
672 
673  FS* clone() const
674  {
675  Mutex::scoped_lock lock(myMutex, false);
676  return Wrap(mySet);
677  }
678 
679  private:
680  typedef tbb::spin_rw_mutex Mutex;
681  mutable Mutex myMutex;
682 
683  boost::weak_ptr<Inner> mySet;
684  };
685 }

Document ID: Generated on Mon Jul 4 01:00:18 EDT 2016 from SVN revision 166489
Copyright © 2005-2015 VT MÄK. All Rights Reserved (www.mak.com)