VR-Forces 4.6 Class Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties 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 isCacheable(const boost::optional<DtFeatureGeometry>& area) const
114  {
115  CPtr handle(This()->getPtr());
116  if (handle)
117  return handle->isCacheable(area);
118  else
119  return FS::isCacheable(area);
120  }
121 
122  void cacheEstimate(double& time, double& size, const boost::optional<DtFeatureGeometry>& area) const
123  {
124  CPtr handle(This()->getPtr());
125  if (handle)
126  handle->cacheEstimate(time, size, area);
127  else
128  return FS::cacheEstimate(time, size, area);
129  }
130 
131  void cacheData(
132  const boost::optional<DtFeatureGeometry>& area,
133  DtFeatureCacheProgressCallback* progress) const
134  {
135  CPtr handle(This()->getPtr());
136  if (handle)
137  handle->cacheData(area, progress);
138  else
139  FS::cacheData(area, progress);
140  }
141 
142  bool loaded(double timeout=0.0) const
143  {
144  CPtr handle(This()->getPtr());
145  if (handle)
146  return handle->loaded(timeout);
147 
148  return false;
149  }
150 
151  virtual bool loadedThrowIfNotSet(double timeout=0.0) const
152  {
153  CPtr handle(This()->getPtr());
154  if (handle)
155  return handle->loaded(timeout);
156 
158  }
159 
161  : public DtObjectDebugger<LoadedCounter>
162  {
164  explicit LoadedCounter(const LoadedCallback& cb) : callback(cb) { }
165  void operator()() const { callback(); }
166  };
167 
169  {
170  if (!cb)
171  DetachCallback();
172 
173  //boost::signals2::connection conn = myLoadedSignal->connect(cb);
174  boost::signals2::connection conn = myLoadedSignal->connect(LoadedCounter(cb));
175 
176  try
177  {
178  return boost::bind(&boost::signals2::connection::disconnect, conn);
179  }
180  catch (...)
181  {
182  conn.disconnect();
183  throw;
184  }
185  }
186 
187  void forEachFeatureParallel(const ForEachFunction& func) const
188  {
189  CPtr handle(This()->getPtr());
190  if (handle)
191  handle->forEachFeatureParallel(func);
192  }
193 
195  {
196  typedef CallbackRecord<ForEachFunction> Record;
197  typedef typename Record::Ptr RecordPtr;
198 
199  DetachCallback detacher;
200 
202  CPtr handle(This()->getPtr());
203  if (handle)
204  detacher = handle->forEachFeatureAsync(func);
205 
207  try
208  {
209  typename CallbackMutex::scoped_lock headLock(myCallbackMutex);
210  RecordPtr newHead(Record::Make(func, myHead, detacher));
211  const_cast<RecordPtr&>(myHead) = newHead;
212  return typename Record::Detacher(newHead);
213  }
214  catch (...)
215  {
216  if (detacher)
217  detacher();
218 
219  throw;
220  }
221  }
222 
224  const DtQuery& query,
225  const boost::optional<DtFeatureGeometry>& geometry,
226  DtLoadType load) const
227  {
228  CPtr handle(This()->getPtr());
229  if (handle)
230  return this->Wrap(handle->filter(query, geometry, load));
231 
233  assert(false);
234  DtTHROW_NEW(DtException, "filtered empty feature set wrapper");
235  }
236 
237  FeatureSet* filter(const DtQuery& query, DtLoadType load) const
238  {
239  return FS::filter(query, load);
240  }
241 
242  FeatureSet* filter(const boost::optional<DtFeatureGeometry>& geometry, DtLoadType load) const
243  {
244  return FS::filter(geometry, load);
245  }
246 
247  public:
248  template <typename Function>
250  : public DtObjectDebugger<DtFeatureSetWrapperCallbackRecordTag>
251  {
252  public:
253  typedef boost::shared_ptr<CallbackRecord> Ptr;
254  typedef boost::weak_ptr<CallbackRecord> WPtr;
255 
256  struct Detacher
257  : public DtObjectDebugger<DtFeatureSetWrapperCallbackRecordDetacherTag>
258  {
259  void operator()() const
260  {
261  boost::shared_ptr<CallbackRecord> callback(callbackWptr.lock());
262  if (callback)
263  callback->detach();
264  }
265 
266  explicit Detacher(const boost::shared_ptr<CallbackRecord>& rec)
267  : callbackWptr(rec) { }
268 
269  boost::weak_ptr<CallbackRecord> callbackWptr;
270  };
271 
272  static Ptr Make(const Function& func, const Ptr& curHead, const DetachCallback& detach)
273  {
274  Ptr newRec(new CallbackRecord(func, curHead, detach));
275  while (newRec->next)
276  {
277  Mutex::scoped_lock lock(newRec->next->mutex);
278  if (newRec->next->func)
279  break;
280 
281  newRec->next = newRec->next->next;
282  }
283 
284  return newRec;
285  }
286 
289  void addCallbacksTo(const CPtr& fs)
290  {
291  Mutex::scoped_lock lock(mutex);
292 
295  if (detacher)
296  {
297  detacher();
299  }
300 
302  if (func && fs)
303  {
304  Function f(func);
305 
306  lock.release();
307  DetachCallback d = fs->forEachFeatureAsync(f);
308  lock.acquire(mutex);
309 
310  if (func)
311  detacher = d;
312  else if (d)
313  d();
314  }
315 
316  Ptr ne = next;
317  lock.release();
318 
319  if (ne)
320  {
321  try
322  {
323  ne->addCallbacksTo(fs);
324  }
325  catch (...)
326  {
327  lock.acquire(mutex);
328  if (detacher)
329  {
330  detacher();
332  }
333 
334  throw;
335  }
336  }
337  }
338 
339  void detach()
340  {
341  Mutex::scoped_lock lock(mutex);
342 
343  if (!func)
344  return;
345 
346  func = Function();
347 
348  if (detacher)
349  {
350  detacher();
352  }
353 
354  Ptr pr = prev.lock();
355  Ptr ne = next;
356 
357  while (pr)
358  {
359  lock.release();
360  lock.acquire(pr->mutex);
361 
362  if (pr->func)
363  break;
364 
365  pr = pr->prev.lock();
366  }
367 
368  while (ne)
369  {
370  Mutex::scoped_lock endLock(ne->mutex);
371  if (ne->func)
372  {
373  if (pr)
374  pr->next = ne;
375 
376  return;
377  }
378 
379  ne = ne->next;
380  }
381 
382  if (pr)
383  pr->next = ne;
384  }
385 
387  {
388  if (detacher)
389  detacher();
390  }
391 
392  typedef tbb::spin_mutex Mutex;
393 
394  private:
395  explicit CallbackRecord(
396  const Function& func,
397  const Ptr& next,
398  const DetachCallback& detach)
399  : func(func)
400  , next(next)
401  , detacher(detach)
402  {
403  }
404 
405  mutable Mutex mutex;
406  Function func;
410  };
411 
412 protected:
413  void setupCallbacks(const CPtr& fs)
414  {
415  typename CallbackMutex::scoped_lock lock(myCallbackMutex);
416 
417  myLoadedSignalDetacher.reset();
418 
419  if (myHead)
420  myHead->addCallbacksTo(fs);
421 
422  if (fs)
423  {
424  myLoadedSignalDetacher.reset(fs->addLoadedCallback(LoadedCaller(myLoadedSignal)));
425 
426  try
427  {
428  if (fs->loaded(0.0))
429  (*myLoadedSignal)();
430  }
431  catch (DtFeatureSetLoadingException&) { }
432  }
433  }
434 
435  private:
436  typedef tbb::spin_mutex CallbackMutex;
437  typedef boost::signals2::signal_type<
438  void (),
439  boost::signals2::keywords::mutex_type<tbb::spin_mutex> >::type LoadedSignal;
440 
441  struct LoadedCaller : public DtObjectDebugger<DtFeatureSetWrapperLoadedCallerTag>
442  {
443  boost::weak_ptr<LoadedSignal> sig;
444  explicit LoadedCaller(const boost::shared_ptr<LoadedSignal>& sig)
445  : sig(sig) { }
446 
447  void operator()() const
448  {
449  boost::shared_ptr<LoadedSignal> signal(sig.lock());
450  if (signal)
451  (*signal)();
452  }
453  };
454 
456  typename CallbackRecord<>::Ptr myHead;
457  boost::shared_ptr<LoadedSignal> myLoadedSignal;
458  typename FeatureSet::DetachScopeGuard myLoadedSignalDetacher;
459  };
460 
461  template <
462  typename FS,
463  template <typename> class PtrTemplate,
464  typename Inner>
465  class DtFeatureSetWrapper;
466 
467  template <typename FS, typename Inner>
468  class DtFeatureSetWrapper<FS,boost::scoped_ptr,Inner> : public FS
469  {
470  public:
471  typedef typename FS::Feature Feature;
472  typedef typename FS::ForEachFunction ForEachFunction;
473  typedef typename FS::LoadedCallback LoadedCallback;
474  typedef typename FS::DetachCallback DetachCallback;
475 
476  explicit DtFeatureSetWrapper(Inner* fs) : mySet(fs)
477  {
478  assert(mySet);
479  }
480 
481  template <typename OtherFS>
482  explicit DtFeatureSetWrapper(std::auto_ptr<OtherFS> fs)
483  : mySet(fs.release())
484  {
485  assert(mySet);
486  }
487 
488  Inner* getPtr() { return mySet.get(); }
489  const Inner* getPtr() const { return mySet.get(); }
490 
491  std::string label() const
492  {
493  return mySet->label();
494  }
495 
496  unsigned numberOfFeatures() const
497  {
498  return mySet->numberOfFeatures();
499  }
500 
501  bool elided() const
502  {
503  return mySet->elided();
504  }
505 
506  bool empty() const
507  {
508  return mySet->empty();
509  }
510 
511  bool isIndexed() const
512  {
513  return mySet->isIndexed();
514  }
515 
516  bool isCacheable(const boost::optional<DtFeatureGeometry>& area) const
517  {
518  return mySet->isCacheable(area);
519  }
520 
521  void cacheEstimate(double& time, double& size, const boost::optional<DtFeatureGeometry>& area) const
522  {
523  mySet->cacheEstimate(time, size, area);
524  }
525 
526  void cacheData(
527  const boost::optional<DtFeatureGeometry>& area,
528  DtFeatureCacheProgressCallback* progress) const
529  {
530  mySet->cacheData(area, progress);
531  }
532 
533  bool loaded(double timeout=0.0) const
534  {
535  return mySet->loaded(timeout);
536  }
537 
538  DetachCallback addLoadedCallback(const LoadedCallback& cb) const
539  {
540  return mySet->addLoadedCallback(cb);
541  }
542 
543  void forEachFeatureParallel(const ForEachFunction& func) const
544  {
545  mySet->forEachFeatureParallel(func);
546  }
547 
548  DetachCallback forEachFeatureAsync(const ForEachFunction& func) const
549  {
550  return mySet->forEachFeatureAsync(func);
551  }
552 
553  FS* filter(
554  const DtQuery& query,
555  const boost::optional<DtFeatureGeometry>& geometry,
556  DtLoadType load) const
557  {
558  return this->Wrap(mySet->filter(query, geometry, load));
559  }
560 
561  FS* clone() const
562  {
563  return this->Wrap(mySet->clone());
564  }
565 
566  private:
567  const boost::scoped_ptr<Inner> mySet;
568  };
569 
570  template <typename FS, typename Inner>
571  class DtFeatureSetWrapper<FS,boost::shared_ptr,Inner>
573  DtFeatureSetWrapper<FS,boost::shared_ptr,Inner>,
574  FS,
575  Inner>
576  {
577  public:
579  {
580  }
581 
582  explicit DtFeatureSetWrapper(Inner* fs)
583  {
584  assert(fs);
585  setPtr(boost::shared_ptr<Inner>(fs));
586  }
587 
588  template <typename OtherFS>
589  explicit DtFeatureSetWrapper(std::auto_ptr<OtherFS> fs)
590  {
591  assert(fs.get());
592  setPtr(boost::shared_ptr<Inner>(fs.release()));
593  }
594 
595  template <typename OtherFS>
596  explicit DtFeatureSetWrapper(const boost::shared_ptr<OtherFS>& fs)
597  {
598  assert(fs.get());
599  setPtr(fs);
600  }
601 
602  boost::shared_ptr<Inner> getPtr()
603  {
604  Mutex::scoped_lock lock(myMutex, false);
605  return mySet;
606  }
607 
608  boost::shared_ptr<const Inner> getPtr() const
609  {
610  Mutex::scoped_lock lock(myMutex, false);
611  return mySet;
612  }
613 
614  boost::shared_ptr<Inner> setPtr(const boost::shared_ptr<Inner>& p)
615  {
616  Mutex::scoped_lock lock(myMutex, false);
617  if (mySet && p)
618  return mySet;
619 
620  if (!lock.upgrade_to_writer() && mySet && p)
621  return mySet;
622 
623  mySet = p;
624 
625  lock.downgrade_to_reader();
626  this->setupCallbacks(p);
627 
628  return mySet;
629  }
630 
631  boost::shared_ptr<Inner> setPtr(Inner* set)
632  {
633  boost::shared_ptr<Inner> fs(set);
634  return setPtr(fs);
635  }
636 
637  FS* clone() const
638  {
639  return this->Wrap(getPtr());
640  }
641 
642  protected:
643  typedef tbb::spin_rw_mutex Mutex;
644  mutable Mutex myMutex;
645 
646  boost::shared_ptr<Inner> mySet;
647  };
648 
649  template <typename FS, typename Inner>
650  class DtFeatureSetWrapper<FS,boost::weak_ptr,Inner>
652  DtFeatureSetWrapper<FS,boost::weak_ptr,Inner>,
653  FS,
654  Inner>
655  {
656  public:
657  typedef typename FS::Feature Feature;
658  typedef typename FS::ForEachFunction ForEachFunction;
659  typedef typename FS::DetachCallback DetachCallback;
660 
662  : mySet() { }
663 
664  template <typename T>
665  explicit DtFeatureSetWrapper(const boost::weak_ptr<T>& fs)
666  {
667  setPtr(fs.lock());
668  }
669 
670  template <typename T>
671  explicit DtFeatureSetWrapper(const boost::shared_ptr<T>& fs)
672  {
673  assert(fs);
674  setPtr(fs);
675  }
676 
677  boost::shared_ptr<Inner> getPtr()
678  {
679  Mutex::scoped_lock lock(myMutex, false);
680  return mySet.lock();
681  }
682 
683  boost::shared_ptr<const Inner> getPtr() const
684  {
685  Mutex::scoped_lock lock(myMutex, false);
686  return mySet.lock();
687  }
688 
689  boost::shared_ptr<Inner> getMutablePtr() const
690  {
691  return const_cast<DtFeatureSetWrapper*>(this)->getPtr();
692  }
693 
694  boost::shared_ptr<Inner> setPtr(const boost::shared_ptr<Inner>& p)
695  {
696  Mutex::scoped_lock lock(myMutex, false);
697  if (p)
698  {
699  boost::shared_ptr<Inner> s(mySet.lock());
700  if (s)
701  return s;
702  }
703 
704  if (!lock.upgrade_to_writer() && p)
705  {
706  boost::shared_ptr<Inner> s(mySet.lock());
707  if (s)
708  return s;
709  }
710 
711  mySet = p;
712 
713  lock.downgrade_to_reader();
714  this->setupCallbacks(p);
715 
716  return p;
717  }
718 
719  FS* clone() const
720  {
721  Mutex::scoped_lock lock(myMutex, false);
722  return this->Wrap(mySet);
723  }
724 
725  private:
726  typedef tbb::spin_rw_mutex Mutex;
727  mutable Mutex myMutex;
728 
729  boost::weak_ptr<Inner> mySet;
730  };
731 }

Document ID: Generated on Thu Apr 12 03:15:37 EDT 2018 from SVN revision 187986
Copyright © 2005-2018 VT MÄK. All Rights Reserved (www.mak.com)