nidas  v1.2-1520
Sample.h
Go to the documentation of this file.
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4; -*-
2 // vim: set shiftwidth=4 softtabstop=4 expandtab:
3 /*
4  ********************************************************************
5  ** NIDAS: NCAR In-situ Data Acquistion Software
6  **
7  ** 2004, Copyright University Corporation for Atmospheric Research
8  **
9  ** This program is free software; you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation; either version 2 of the License, or
12  ** (at your option) any later version.
13  **
14  ** This program is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** The LICENSE.txt file accompanying this software contains
20  ** a copy of the GNU General Public License. If it is not found,
21  ** write to the Free Software Foundation, Inc.,
22  ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  **
24  ********************************************************************
25 */
26 /*
27 
28  Some over-engineered sample classes.
29 
30 */
31 
32 #ifndef NIDAS_CORE_SAMPLET_H
33 #define NIDAS_CORE_SAMPLET_H
34 
35 #include "SampleLengthException.h"
37 #include <nidas/util/MutexCount.h>
39 #include <nidas/linux/types.h>
40 
41 #include <climits>
42 #include <iostream>
43 #include <cstring>
44 
45 #include <cmath>
46 
47 #include "sample_type_traits.h"
48 
49 namespace nidas { namespace core {
50 
54 extern const float floatNAN;
55 
56 extern const double doubleNAN;
57 
61 typedef long long dsm_time_t;
62 
63 typedef unsigned int dsm_sample_id_t;
64 
75 #define GET_SAMPLE_TYPE(tid) ((tid) >> 26)
76 #define SET_SAMPLE_TYPE(tid,val) (((tid) & 0x03ffffff) | ((unsigned int)(val) << 26))
77 
78 #define GET_FULL_ID(tid) ((tid) & 0x03ffffff)
79 #define SET_FULL_ID(tid,val) (((tid) & 0xfc000000) | ((val) & 0x03ffffff))
80 
81 #define GET_DSM_ID(tid) (((tid) & 0x03ff0000) >> 16)
82 #define SET_DSM_ID(tid,val) (((tid) & 0xfc00ffff) | (((unsigned int)(val) & 0x3ff) << 16))
83 
84 #define GET_SPS_ID(tid) ((tid) & 0xffff)
85 #define GET_SHORT_ID(tid) ((tid) & 0xffff)
86 
87 #define SET_SPS_ID(tid,val) (((tid) & 0xffff0000) | ((val) & 0xffff))
88 #define SET_SHORT_ID(tid,val) (((tid) & 0xffff0000) | ((val) & 0xffff))
89 
94 #define MUTEX_PROTECT_REF_COUNTS
95 
100 // #define USE_ATOMIC_REF_COUNT
101 
107 public:
108 
110  _tt(0),_length(0),_tid((unsigned int)t << 26) {}
111 
112  dsm_time_t getTimeTag() const { return _tt; }
113 
114  void setTimeTag(dsm_time_t val) { _tt = val; }
115 
120  unsigned int getDataByteLength() const { return _length; }
121 
126  void setDataByteLength(unsigned int val) { _length = val; }
127 
128  dsm_sample_id_t getId() const { return GET_FULL_ID(_tid); }
129  void setId(dsm_sample_id_t val) { _tid = SET_FULL_ID(_tid,val); }
130 
131  dsm_sample_id_t getRawId() const { return _tid; }
132  void setRawId(dsm_sample_id_t val) { _tid = val; }
133 
137  unsigned int getDSMId() const { return GET_DSM_ID(_tid); }
138  void setDSMId(unsigned int val) { _tid = SET_DSM_ID(_tid,val); }
139 
143  unsigned int getSpSId() const { return GET_SPS_ID(_tid); }
144  void setSpSId(unsigned int val) { _tid = SET_SPS_ID(_tid,val); }
145 
150  unsigned char getType() const { return GET_SAMPLE_TYPE(_tid); }
151 
152  static unsigned int getSizeOf()
153  {
154  return sizeof(dsm_time_t) + sizeof(dsm_sample_length_t) +
155  sizeof(dsm_sample_id_t); }
156 
157  static unsigned int getMaxDataLength() { return maxValue(dsm_sample_length_t()); }
158 
159 protected:
160 
165 
171 
183 };
184 
189 class Sample {
190 public:
191 
193  _header(t),_refCount(1),_refLock()
194  {
195  ++_nsamps;
196  }
197 
198  virtual ~Sample() { --_nsamps; }
199 
201 
205  dsm_time_t getTimeTag() const { return _header.getTimeTag(); }
206 
212  void setId(dsm_sample_id_t val) { _header.setId(val); }
213 
217  dsm_sample_id_t getId() const { return _header.getId(); }
218 
227 
228  dsm_sample_id_t getRawId() const { return _header.getRawId(); }
229 
235  void setSpSId(unsigned int val) { _header.setSpSId(val); }
236 
241  unsigned int getSpSId() const { return _header.getSpSId(); }
242 
246  void setDSMId(unsigned int val) { _header.setDSMId(val); }
247 
251  unsigned int getDSMId() const { return _header.getDSMId(); }
252 
256  unsigned int getDataByteLength() const { return _header.getDataByteLength(); }
257 
261  virtual void setDataLength(unsigned int val) = 0;
262 
266  virtual unsigned int getDataLength() const = 0;
267 
271  virtual sampleType getType() const = 0;
272 
276  unsigned int getHeaderLength() const { return SampleHeader::getSizeOf(); }
277 
281  const void* getHeaderPtr() const { return &_header; }
282 
286  virtual void* getVoidDataPtr() = 0;
287 
291  virtual const void* getConstVoidDataPtr() const = 0;
292 
297  virtual double getDataValue(unsigned int i) const = 0;
298 
303  virtual void setDataValue(unsigned int i,double val) = 0;
304 
309  virtual void setDataValue(unsigned int i,float val) = 0;
310 
314  virtual unsigned int getAllocLength() const = 0;
315 
319  virtual unsigned int getAllocByteLength() const = 0;
320 
324  virtual void allocateData(unsigned int val) = 0;
325 
329  virtual void reallocateData(unsigned int val) = 0;
330 
339  void holdReference() const {
340 #ifdef USE_ATOMIC_REF_COUNT
341  __sync_add_and_fetch(&_refCount,1);
342 #else
343 #ifdef MUTEX_PROTECT_REF_COUNTS
344  _refLock.lock();
345 #endif
346  _refCount++;
347 #ifdef MUTEX_PROTECT_REF_COUNTS
348  _refLock.unlock();
349 #endif
350 #endif
351  }
352 
356  virtual void freeReference() const = 0;
357 
358 protected:
359 
361 
365  mutable int _refCount;
366 
367 #ifdef MUTEX_PROTECT_REF_COUNTS
369 #endif
370 
376 #ifndef PROTECT_NSAMPLES
377  static int _nsamps;
378 #ifdef ENABLE_VALGRIND
379 public:
380  class InitValgrind;
381 protected:
382  friend class InitValgrind;
383 #endif
384 #else
386 #endif
387 };
388 
392 template <class DataT>
393 class SampleT : public Sample {
394 public:
395 
396  // Technically speaking, I think it is unsafe to call the subclass
397  // method getType() when calling the base class constructor, because
398  // the subclass has not been initialized yet. It works here probably
399  // because GCC binds directly to the subclass getSampleType() method,
400  // probably because of some obscure C++ scoping rules. If it didn't,
401  // then the call would fail since the VTable has not been fully
402  // initialized yet, or if it is it is initialized with the base class
403  // bindings, for which getType() is pure virtual.
404 
405  // Therefore the getType() call has been replaced with getSampleType().
406  // That seems safer as long as that call only depends upon on the
407  // operand type and not on its value, since its value is an
408  // uninitialized pointer member.
409  //
410  // An alternative to calling a function at all is to use type traits
411  // templates, such as defined in sample_traits.h:
412  //
413  // Sample(sample_type_traits<DataT>::sample_type_enum)
414 
416  Sample(sample_type_traits<DataT>::sample_type_enum),
417  _data(0),_allocLen(0)
418  {}
419 
420  ~SampleT() { delete [] _data; }
421 
422  sampleType getType() const { return getSampleType(_data); }
423 
427  unsigned int getDataLength() const
428  {
429  return getDataByteLength() / sizeof(DataT);
430  }
431 
436  void setDataLength(unsigned int val)
437  {
438  if (val > getAllocLength())
439  throw SampleLengthException(
440  "SampleT::setDataLength:",val,getAllocLength());
441  _header.setDataByteLength(val * sizeof(DataT));
442  }
443 
447  static unsigned int getMaxDataLength()
448  {
449  return SampleHeader::getMaxDataLength() / sizeof(DataT);
450  }
451 
452  void* getVoidDataPtr() { return (void*) _data; }
453  const void* getConstVoidDataPtr() const { return (const void*) _data; }
454 
455  DataT* getDataPtr() { return _data; }
456 
457  const DataT* getConstDataPtr() const { return _data; }
458 
462  double getDataValue(unsigned int i) const
463  {
464  return (double)_data[i];
465  }
466 
470  void setDataValue(unsigned int i, double val)
471  {
472  _data[i] = (DataT)val;
473  }
474 
478  void setDataValue(unsigned int i, float val)
479  {
480  _data[i] = (DataT)val;
481  }
482 
486  unsigned int getAllocLength() const { return _allocLen / sizeof(DataT); }
487 
491  unsigned int getAllocByteLength() const { return _allocLen; }
492 
497  void allocateData(unsigned int val) {
498  if (val > getMaxDataLength())
499  throw SampleLengthException(
500  "SampleT::allocateData:",val,getMaxDataLength());
501  if (_allocLen < val * sizeof(DataT)) {
502  delete [] _data;
503  _data = new DataT[val];
504  _allocLen = val * sizeof(DataT);
505  setDataLength(0);
506  }
507  }
508 
513  void reallocateData(unsigned int val) {
514  if (val > getMaxDataLength())
515  throw SampleLengthException(
516  "SampleT::reallocateData:",val,getMaxDataLength());
517  if (_allocLen < val * sizeof(DataT)) {
518  DataT* newdata = new DataT[val];
519  std::memcpy(newdata,_data,_allocLen);
520  delete [] _data;
521  _data = newdata;
522  _allocLen = val * sizeof(DataT);
523  }
524  }
525 
526  static int sizeofDataType() { return sizeof(DataT); }
527 
577  void freeReference() const;
578 
579 protected:
580 
584  DataT* _data;
585 
589  unsigned int _allocLen;
590 
592  SampleT(const SampleT&);
593 
595  SampleT& operator=(const SampleT&);
596 };
597 
603 Sample* getSample(sampleType type, unsigned int len);
604 
605 }} // namespace nidas namespace core
606 
607 // Here we define methods which use both the SampleT and SamplePool class.
608 // We wait until now to include SamplePool.h since it needs to have
609 // the SampleT class defined. We must exit the dsm namespace before
610 // including SamplePool.h
611 
612 #include "SamplePool.h"
613 
614 namespace nidas { namespace core {
615 
619 template <class T>
620 SampleT<T>* getSample(unsigned int len)
621 {
622  SampleT<T>* samp =
623  SamplePool<SampleT<T> >::getInstance()->getSample(len);
624  return samp;
625 }
626 
631 template <class DataT>
633 {
634  // if refCount is 0, put it back in the Pool.
635 #ifdef USE_ATOMIC_REF_COUNT
636  // GCC 4.X atomic operations
637  int rc = __sync_sub_and_fetch(&_refCount,1);
638  assert(rc >= 0);
639  if (rc == 0)
640  SamplePool<SampleT<DataT> >::getInstance()->putSample(this);
641 #else
642 #ifdef MUTEX_PROTECT_REF_COUNTS
643  _refLock.lock();
644 #endif
645  bool ref0 = --_refCount == 0;
646  assert(_refCount >= 0);
647 #ifdef MUTEX_PROTECT_REF_COUNTS
648  _refLock.unlock();
649 #endif
650  if (ref0)
651  SamplePool<SampleT<DataT> >::getInstance()->putSample(this);
652 #endif
653 }
654 
655 }} // namespace nidas namespace core
656 
657 #endif
unsigned int getAllocLength() const
Get number of elements allocated in data portion of sample.
Definition: Sample.h:486
dsm_sample_id_t getId() const
Definition: Sample.h:128
SampleType * getSample(unsigned int len)
Get a sample of at least len elements from the pool.
Definition: SamplePool.h:258
unsigned char getType() const
Get the data type of this sample.
Definition: Sample.h:150
virtual void * getVoidDataPtr()=0
Get a void* pointer to the data portion of the sample.
const void * getHeaderPtr() const
Get a pointer to the header portion of the sample.
Definition: Sample.h:281
void reallocateData(unsigned int val)
Re-allocate data, space, keeping contents.
Definition: Sample.h:513
#define GET_DSM_ID(tid)
Definition: Sample.h:81
void putSample(const SampleType *)
Return a sample to the pool.
Definition: SamplePool.h:346
sampleType
Definition: sample_type_traits.h:30
sampleType getSampleType(T *)
Definition: sample_type_traits.h:111
void freeReference() const
Decrement the reference count for this sample.
Definition: Sample.h:632
Definition: sample_type_traits.h:31
#define SET_DSM_ID(tid, val)
Definition: Sample.h:82
unsigned int dsm_sample_id_t
Definition: Sample.h:63
SampleT()
Definition: Sample.h:415
void setSpSId(unsigned int val)
Definition: Sample.h:144
#define GET_FULL_ID(tid)
Definition: Sample.h:78
The gcc buildin atomic operations are not supported on arm, and one must use -march=i686 for them to ...
Definition: Sample.h:106
unsigned int getAllocByteLength() const
Get number of bytes allocated in data portion of sample.
Definition: Sample.h:491
unsigned int getDataByteLength() const
Get the value of the length member of the header.
Definition: Sample.h:120
virtual void freeReference() const =0
Decrement the reference count for this sample.
unsigned int maxValue(unsigned short)
maxValue is an overloaded function returning the maximum value of its integer argument.
Definition: sample_type_traits.h:10
long long dsm_time_t
Posix time in microseconds, the number of non-leap microseconds since 1970 Jan 1 00:00 UTC...
Definition: Sample.h:61
dsm_time_t _tt
Time-tag in non-leap microseconds since Jan 1, 1970 00:00 GMT.
Definition: Sample.h:164
#define SET_FULL_ID(tid, val)
Definition: Sample.h:79
nidas::util::Mutex _refLock
Definition: Sample.h:368
virtual unsigned int getDataLength() const =0
Get the number of elements in data portion of sample.
const float floatNAN
Value of a float NAN for general use.
Definition: Sample.cc:31
void allocateData(unsigned int val)
Allocate data.
Definition: Sample.h:497
const double doubleNAN
Definition: Sample.cc:33
virtual unsigned int getAllocLength() const =0
Get number of elements allocated in data portion of sample.
dsm_sample_id_t getRawId() const
Definition: Sample.h:131
DataT * _data
Pointer to the actual data.
Definition: Sample.h:584
dsm_sample_id_t getRawId() const
Definition: Sample.h:228
void setId(dsm_sample_id_t val)
Set the id portion of the sample header.
Definition: Sample.h:212
unsigned int _allocLen
Number of bytes allocated in data.
Definition: Sample.h:589
virtual void reallocateData(unsigned int val)=0
Re-allocate a number of bytes of data, saving old contents.
virtual ~Sample()
Definition: Sample.h:198
virtual unsigned int getAllocByteLength() const =0
Get number of bytes allocated in data portion of sample.
void setDataValue(unsigned int i, double val)
Implementation of virtual method.
Definition: Sample.h:470
virtual const void * getConstVoidDataPtr() const =0
Get a const void* pointer to the data portion of the sample.
unsigned int getDSMId() const
Get the DSM identifier for the sample.
Definition: Sample.h:137
void setDataByteLength(unsigned int val)
Set the length member of the header.
Definition: Sample.h:126
void setTimeTag(dsm_time_t val)
Definition: Sample.h:200
void setDataLength(unsigned int val)
Set the number of elements of type DataT in data.
Definition: Sample.h:436
unsigned int getHeaderLength() const
Number of bytes in header.
Definition: Sample.h:276
dsm_time_t getTimeTag() const
Time-tag in non-leap microseconds since Jan 1, 1970 00:00 GMT.
Definition: Sample.h:205
dsm_sample_id_t getId() const
Get the id portion of the sample header.
Definition: Sample.h:217
dsm_sample_id_t _tid
An identifier for this sample consisting of packed bit fields.
Definition: Sample.h:182
Definition: SampleLengthException.h:35
void setDataValue(unsigned int i, float val)
Implementation of virtual method.
Definition: Sample.h:478
void setRawId(dsm_sample_id_t val)
Set the full, raw id portion of the sample header.
Definition: Sample.h:226
unsigned int getDSMId() const
Get the DSM (data system) id portion of the sample header.
Definition: Sample.h:251
#define GET_SAMPLE_TYPE(tid)
macros to get and set fields of the tid member of a Sample.
Definition: Sample.h:75
void setId(dsm_sample_id_t val)
Definition: Sample.h:129
void setSpSId(unsigned int val)
Set the short id portion of the sample header, containing the sensor + sample ids.
Definition: Sample.h:235
virtual sampleType getType() const =0
Get the type of the sample.
A typed Sample, with data of type DataT.
Definition: Sample.h:393
Sample * getSample(sampleType type, unsigned int len)
A convienence method for getting a sample of an enumerated type from a pool.
Definition: Sample.cc:70
void lock()
Lock the Mutex.
Definition: ThreadSupport.h:206
unsigned int getSpSId() const
Get the short id portion of the sample header.
Definition: Sample.h:241
int len
Definition: sing.cc:934
Interface to a data sample.
Definition: Sample.h:189
SampleHeader(sampleType t=CHAR_ST)
Definition: Sample.h:109
void holdReference() const
Increment the reference count for this sample.
Definition: Sample.h:339
DataT * getDataPtr()
Definition: Sample.h:455
const DataT * getConstDataPtr() const
Definition: Sample.h:457
virtual double getDataValue(unsigned int i) const =0
Get the numeric value of data element i.
double getDataValue(unsigned int i) const
Implementation of virtual method.
Definition: Sample.h:462
static unsigned int getMaxDataLength()
Definition: Sample.h:157
unsigned int getSpSId() const
Get the sample identifier for the sample.
Definition: Sample.h:143
unsigned int getDataByteLength() const
Get the number of bytes in data portion of sample.
Definition: Sample.h:256
sampleType getType() const
Get the type of the sample.
Definition: Sample.h:422
int _refCount
The reference count.
Definition: Sample.h:365
SampleHeader _header
Definition: Sample.h:360
static int sizeofDataType()
Definition: Sample.h:526
static unsigned int getSizeOf()
Definition: Sample.h:152
~SampleT()
Definition: Sample.h:420
void setDSMId(unsigned int val)
Definition: Sample.h:138
A class which wraps a numeric value and guards operations on it with a Mutex.
Definition: MutexCount.h:30
unsigned int dsm_sample_length_t
length of data portion of sample.
Definition: types.h:51
A pool of Samples.
Definition: SamplePool.h:98
void setRawId(dsm_sample_id_t val)
Definition: Sample.h:132
virtual void allocateData(unsigned int val)=0
Allocate a number of bytes of data.
dsm_sample_length_t _length
Length of data (# of bytes) in the sample - does not include header fields.
Definition: Sample.h:170
static unsigned int getMaxDataLength()
Maximum number of elements in data.
Definition: Sample.h:447
virtual void setDataValue(unsigned int i, double val)=0
Set the value of data element i to a double.
void * getVoidDataPtr()
Get a void* pointer to the data portion of the sample.
Definition: Sample.h:452
#define GET_SPS_ID(tid)
Definition: Sample.h:84
void setTimeTag(dsm_time_t val)
Definition: Sample.h:114
static int _nsamps
Global count of the number of samples in use by a process.
Definition: Sample.h:377
Sample(sampleType t=CHAR_ST)
Definition: Sample.h:192
const void * getConstVoidDataPtr() const
Get a const void* pointer to the data portion of the sample.
Definition: Sample.h:453
A C++ wrapper for a POSIX mutex.
Definition: ThreadSupport.h:154
#define SET_SPS_ID(tid, val)
Definition: Sample.h:87
SampleT & operator=(const SampleT &)
No assignment.
void setDSMId(unsigned int val)
Set the DSM (data system) id portion of the sample header.
Definition: Sample.h:246
virtual void setDataLength(unsigned int val)=0
Set the number of elements in data portion of sample.
unsigned int getDataLength() const
Get number of elements of type DataT in data.
Definition: Sample.h:427
Definition: sample_type_traits.h:45
void unlock()
Unlock the Mutex.
Definition: ThreadSupport.h:218
dsm_time_t getTimeTag() const
Definition: Sample.h:112