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

Document ID: Generated on Wed Mar 11 21:20:57 EDT 2015 from SVN revision 150940
Copyright © 2005-2014 VT MÄK. All Rights Reserved (www.mak.com)