nidas v1.2.3
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
39#include <nidas/linux/types.h>
40
41#include <climits>
42#include <iostream>
43#include <cstring>
44#include <initializer_list>
45
46#include <cmath>
47
48#include "sample_type_traits.h"
49
50namespace nidas { namespace core {
51
55extern const float floatNAN;
56
57extern const double doubleNAN;
58
62typedef long long dsm_time_t;
63
64typedef unsigned int dsm_sample_id_t;
65
76#define GET_SAMPLE_TYPE(tid) ((tid) >> 26)
77#define SET_SAMPLE_TYPE(tid,val) (((tid) & 0x03ffffff) | ((unsigned int)(val) << 26))
78
79#define GET_FULL_ID(tid) ((tid) & 0x03ffffff)
80#define SET_FULL_ID(tid,val) (((tid) & 0xfc000000) | ((val) & 0x03ffffff))
81
82#define GET_DSM_ID(tid) (((tid) & 0x03ff0000) >> 16)
83#define SET_DSM_ID(tid,val) (((tid) & 0xfc00ffff) | (((unsigned int)(val) & 0x3ff) << 16))
84
85#define GET_SPS_ID(tid) ((tid) & 0xffff)
86#define GET_SHORT_ID(tid) ((tid) & 0xffff)
87
88#define SET_SPS_ID(tid,val) (((tid) & 0xffff0000) | ((val) & 0xffff))
89#define SET_SHORT_ID(tid,val) (((tid) & 0xffff0000) | ((val) & 0xffff))
90
95#define MUTEX_PROTECT_REF_COUNTS
96
101// #define USE_ATOMIC_REF_COUNT
102
108public:
109
111 _tt(0),_length(0),_tid((unsigned int)t << 26) {}
112
113 dsm_time_t getTimeTag() const { return _tt; }
114
115 void setTimeTag(dsm_time_t val) { _tt = val; }
116
121 unsigned int getDataByteLength() const { return _length; }
122
127 void setDataByteLength(unsigned int val) { _length = val; }
128
131
132 dsm_sample_id_t getRawId() const { return _tid; }
134
138 unsigned int getDSMId() const { return GET_DSM_ID(_tid); }
139 void setDSMId(unsigned int val) { _tid = SET_DSM_ID(_tid,val); }
140
144 unsigned int getSpSId() const { return GET_SPS_ID(_tid); }
145 void setSpSId(unsigned int val) { _tid = SET_SPS_ID(_tid,val); }
146
151 unsigned char getType() const { return GET_SAMPLE_TYPE(_tid); }
152
153 static unsigned int getSizeOf()
154 {
155 return sizeof(dsm_time_t) + sizeof(dsm_sample_length_t) +
156 sizeof(dsm_sample_id_t); }
157
158 static unsigned int getMaxDataLength() { return maxValue(dsm_sample_length_t()); }
159
160protected:
161
166
172
184};
185
190class Sample {
191public:
192
195 {
196 ++_nsamps;
197 }
198
199 virtual ~Sample() { --_nsamps; }
200
202
207
213 void setId(dsm_sample_id_t val) { _header.setId(val); }
214
218 dsm_sample_id_t getId() const { return _header.getId(); }
219
228
230
236 void setSpSId(unsigned int val) { _header.setSpSId(val); }
237
242 unsigned int getSpSId() const { return _header.getSpSId(); }
243
247 void setDSMId(unsigned int val) { _header.setDSMId(val); }
248
252 unsigned int getDSMId() const { return _header.getDSMId(); }
253
257 unsigned int getDataByteLength() const { return _header.getDataByteLength(); }
258
262 virtual void setDataLength(unsigned int val) = 0;
263
267 virtual unsigned int getDataLength() const = 0;
268
272 virtual sampleType getType() const = 0;
273
277 unsigned int getHeaderLength() const { return SampleHeader::getSizeOf(); }
278
282 const void* getHeaderPtr() const { return &_header; }
283
287 virtual void* getVoidDataPtr() = 0;
288
292 virtual const void* getConstVoidDataPtr() const = 0;
293
298 virtual double getDataValue(unsigned int i) const = 0;
299
304 virtual void setDataValue(unsigned int i,double val) = 0;
305
310 virtual void setDataValue(unsigned int i,float val) = 0;
311
315 virtual unsigned int getAllocLength() const = 0;
316
320 virtual unsigned int getAllocByteLength() const = 0;
321
325 virtual void allocateData(unsigned int val) = 0;
326
330 virtual void reallocateData(unsigned int val) = 0;
331
340 void holdReference() const {
341#ifdef USE_ATOMIC_REF_COUNT
343#else
344#ifdef MUTEX_PROTECT_REF_COUNTS
345 _refLock.lock();
346#endif
347 _refCount++;
348#ifdef MUTEX_PROTECT_REF_COUNTS
350#endif
351#endif
352 }
353
357 virtual void freeReference() const = 0;
358
359protected:
360
362
366 mutable int _refCount;
367
368#ifdef MUTEX_PROTECT_REF_COUNTS
370#endif
371
377#ifndef PROTECT_NSAMPLES
378 static int _nsamps;
379#ifdef ENABLE_VALGRIND
380public:
381 class InitValgrind;
382protected:
383 friend class InitValgrind;
384#endif
385#else
387#endif
388};
389
393template <class DataT>
394class SampleT : public Sample {
395public:
396
397 // Technically speaking, I think it is unsafe to call the subclass
398 // method getType() when calling the base class constructor, because
399 // the subclass has not been initialized yet. It works here probably
400 // because GCC binds directly to the subclass getSampleType() method,
401 // probably because of some obscure C++ scoping rules. If it didn't,
402 // then the call would fail since the VTable has not been fully
403 // initialized yet, or if it is it is initialized with the base class
404 // bindings, for which getType() is pure virtual.
405
406 // Therefore the getType() call has been replaced with getSampleType().
407 // That seems safer as long as that call only depends upon on the
408 // operand type and not on its value, since its value is an
409 // uninitialized pointer member.
410 //
411 // An alternative to calling a function at all is to use type traits
412 // templates, such as defined in sample_traits.h:
413 //
414 // Sample(sample_type_traits<DataT>::sample_type_enum)
415
417 Sample(sample_type_traits<DataT>::sample_type_enum),
418 _data(0),_allocLen(0)
419 {}
420
421 void
422 setValues(std::initializer_list<DataT> values)
423 {
424 unsigned int len = values.size();
427 unsigned int i = 0;
428 for (auto v : values)
429 {
430 setDataValue(i++, (DataT)v);
431 }
432 }
433
442 SampleT(std::initializer_list<DataT> values) :
443 Sample(sample_type_traits<DataT>::sample_type_enum),
444 _data(0),_allocLen(0)
445 {
446 setValues(values);
447 }
448
449 ~SampleT() { delete [] _data; }
450
452
456 unsigned int getDataLength() const
457 {
458 return getDataByteLength() / sizeof(DataT);
459 }
460
465 void setDataLength(unsigned int val)
466 {
467 if (val > getAllocLength())
469 "SampleT::setDataLength:",val,getAllocLength());
470 _header.setDataByteLength(val * sizeof(DataT));
471 }
472
476 static unsigned int getMaxDataLength()
477 {
478 return SampleHeader::getMaxDataLength() / sizeof(DataT);
479 }
480
481 void* getVoidDataPtr() { return (void*) _data; }
482 const void* getConstVoidDataPtr() const { return (const void*) _data; }
483
484 DataT* getDataPtr() { return _data; }
485
486 const DataT* getConstDataPtr() const { return _data; }
487
491 double getDataValue(unsigned int i) const
492 {
493 return (double)_data[i];
494 }
495
499 void setDataValue(unsigned int i, double val)
500 {
501 _data[i] = (DataT)val;
502 }
503
507 void setDataValue(unsigned int i, float val)
508 {
509 _data[i] = (DataT)val;
510 }
511
515 unsigned int getAllocLength() const { return _allocLen / sizeof(DataT); }
516
520 unsigned int getAllocByteLength() const { return _allocLen; }
521
526 void allocateData(unsigned int val) {
527 if (val > getMaxDataLength())
529 "SampleT::allocateData:",val,getMaxDataLength());
530 if (_allocLen < val * sizeof(DataT)) {
531 delete [] _data;
532 _data = new DataT[val];
533 _allocLen = val * sizeof(DataT);
534 setDataLength(0);
535 }
536 }
537
542 void reallocateData(unsigned int val) {
543 if (val > getMaxDataLength())
545 "SampleT::reallocateData:",val,getMaxDataLength());
546 if (_allocLen < val * sizeof(DataT)) {
547 DataT* newdata = new DataT[val];
548 std::memcpy(newdata,_data,_allocLen);
549 delete [] _data;
550 _data = newdata;
551 _allocLen = val * sizeof(DataT);
552 }
553 }
554
555 static int sizeofDataType() { return sizeof(DataT); }
556
606 void freeReference() const;
607
608protected:
609
613 DataT* _data;
614
618 unsigned int _allocLen;
619
622
625};
626
627
628class SampleChar : public SampleT<char>
629{
630public:
639 SampleChar(const char* buffer)
640 {
641 unsigned int len = strlen(buffer) + 1;
645 }
646};
647
653Sample* getSample(sampleType type, unsigned int len);
654
655}} // namespace nidas namespace core
656
657// Here we define methods which use both the SampleT and SamplePool class.
658// We wait until now to include SamplePool.h since it needs to have
659// the SampleT class defined. We must exit the dsm namespace before
660// including SamplePool.h
661
662#include "SamplePool.h"
663
664namespace nidas { namespace core {
665
669template <class T>
670SampleT<T>* getSample(unsigned int len)
671{
672 SampleT<T>* samp =
673 SamplePool<SampleT<T> >::getInstance()->getSample(len);
674 return samp;
675}
676
684SampleT<char>* getSample(const char* data);
685
690template <class DataT>
692{
693 // if refCount is 0, put it back in the Pool.
694#ifdef USE_ATOMIC_REF_COUNT
695 // GCC 4.X atomic operations
696 int rc = __sync_sub_and_fetch(&_refCount,1);
697 assert(rc >= 0);
698 if (rc == 0)
699 SamplePool<SampleT<DataT> >::getInstance()->putSample(this);
700#else
701#ifdef MUTEX_PROTECT_REF_COUNTS
702 _refLock.lock();
703#endif
704 bool ref0 = --_refCount == 0;
705 assert(_refCount >= 0);
706#ifdef MUTEX_PROTECT_REF_COUNTS
707 _refLock.unlock();
708#endif
709 if (ref0)
710 SamplePool<SampleT<DataT> >::getInstance()->putSample(this);
711#endif
712}
713
714}} // namespace nidas namespace core
715
716#endif
#define GET_FULL_ID(tid)
Definition Sample.h:79
#define GET_SPS_ID(tid)
Definition Sample.h:85
#define SET_SPS_ID(tid, val)
Definition Sample.h:88
#define GET_DSM_ID(tid)
Definition Sample.h:82
#define GET_SAMPLE_TYPE(tid)
macros to get and set fields of the tid member of a Sample.
Definition Sample.h:76
#define SET_DSM_ID(tid, val)
Definition Sample.h:83
#define SET_FULL_ID(tid, val)
Definition Sample.h:80
Definition Sample.h:629
SampleChar(const char *buffer)
Construct a SampleT<char> initialized to the bytes in buffer.
Definition Sample.h:639
The gcc buildin atomic operations are not supported on arm, and one must use -march=i686 for them to ...
Definition Sample.h:107
void setSpSId(unsigned int val)
Definition Sample.h:145
static unsigned int getMaxDataLength()
Definition Sample.h:158
void setTimeTag(dsm_time_t val)
Definition Sample.h:115
dsm_sample_id_t getId() const
Definition Sample.h:129
unsigned int getDataByteLength() const
Get the value of the length member of the header.
Definition Sample.h:121
dsm_time_t getTimeTag() const
Definition Sample.h:113
void setDSMId(unsigned int val)
Definition Sample.h:139
void setDataByteLength(unsigned int val)
Set the length member of the header.
Definition Sample.h:127
SampleHeader(sampleType t=CHAR_ST)
Definition Sample.h:110
dsm_sample_length_t _length
Length of data (# of bytes) in the sample - does not include header fields.
Definition Sample.h:171
dsm_sample_id_t _tid
An identifier for this sample consisting of packed bit fields.
Definition Sample.h:183
void setRawId(dsm_sample_id_t val)
Definition Sample.h:133
dsm_sample_id_t getRawId() const
Definition Sample.h:132
void setId(dsm_sample_id_t val)
Definition Sample.h:130
unsigned int getDSMId() const
Get the DSM identifier for the sample.
Definition Sample.h:138
static unsigned int getSizeOf()
Definition Sample.h:153
dsm_time_t _tt
Time-tag in non-leap microseconds since Jan 1, 1970 00:00 GMT.
Definition Sample.h:165
unsigned int getSpSId() const
Get the sample identifier for the sample.
Definition Sample.h:144
unsigned char getType() const
Get the data type of this sample.
Definition Sample.h:151
Definition SampleLengthException.h:35
A typed Sample, with data of type DataT.
Definition Sample.h:394
static int sizeofDataType()
Definition Sample.h:555
void allocateData(unsigned int val)
Allocate data.
Definition Sample.h:526
void setDataLength(unsigned int val)
Set the number of elements of type DataT in data.
Definition Sample.h:465
void * getVoidDataPtr()
Get a void* pointer to the data portion of the sample.
Definition Sample.h:481
const void * getConstVoidDataPtr() const
Get a const void* pointer to the data portion of the sample.
Definition Sample.h:482
SampleT(const SampleT &)
No copy.
unsigned int getAllocLength() const
Get number of elements allocated in data portion of sample.
Definition Sample.h:515
unsigned int getAllocByteLength() const
Get number of bytes allocated in data portion of sample.
Definition Sample.h:520
void reallocateData(unsigned int val)
Re-allocate data, space, keeping contents.
Definition Sample.h:542
unsigned int getDataLength() const
Get number of elements of type DataT in data.
Definition Sample.h:456
void setDataValue(unsigned int i, float val)
Implementation of virtual method.
Definition Sample.h:507
double getDataValue(unsigned int i) const
Implementation of virtual method.
Definition Sample.h:491
const DataT * getConstDataPtr() const
Definition Sample.h:486
SampleT()
Definition Sample.h:416
void freeReference() const
Decrement the reference count for this sample.
Definition Sample.h:691
void setValues(std::initializer_list< DataT > values)
Definition Sample.h:422
DataT * getDataPtr()
Definition Sample.h:484
DataT * _data
Pointer to the actual data.
Definition Sample.h:613
void setDataValue(unsigned int i, double val)
Implementation of virtual method.
Definition Sample.h:499
SampleT & operator=(const SampleT &)
No assignment.
static unsigned int getMaxDataLength()
Maximum number of elements in data.
Definition Sample.h:476
~SampleT()
Definition Sample.h:449
unsigned int _allocLen
Number of bytes allocated in data.
Definition Sample.h:618
sampleType getType() const
Get the type of the sample.
Definition Sample.h:451
SampleT(std::initializer_list< DataT > values)
Construct a SampleT from an initializer list.
Definition Sample.h:442
Interface to a data sample.
Definition Sample.h:190
int _refCount
The reference count.
Definition Sample.h:366
virtual void reallocateData(unsigned int val)=0
Re-allocate a number of bytes of data, saving old contents.
void setDSMId(unsigned int val)
Set the DSM (data system) id portion of the sample header.
Definition Sample.h:247
virtual double getDataValue(unsigned int i) const =0
Get the numeric value of data element i.
const void * getHeaderPtr() const
Get a pointer to the header portion of the sample.
Definition Sample.h:282
dsm_sample_id_t getRawId() const
Definition Sample.h:229
virtual void freeReference() const =0
Decrement the reference count for this sample.
SampleHeader _header
Definition Sample.h:361
unsigned int getDSMId() const
Get the DSM (data system) id portion of the sample header.
Definition Sample.h:252
virtual void allocateData(unsigned int val)=0
Allocate a number of bytes of data.
virtual ~Sample()
Definition Sample.h:199
virtual sampleType getType() const =0
Get the type of the sample.
virtual unsigned int getAllocByteLength() const =0
Get number of bytes allocated in data portion of sample.
virtual void setDataValue(unsigned int i, float val)=0
Set the value of data element i to a float.
virtual void setDataLength(unsigned int val)=0
Set the number of elements in data portion of sample.
void setRawId(dsm_sample_id_t val)
Set the full, raw id portion of the sample header.
Definition Sample.h:227
dsm_sample_id_t getId() const
Get the id portion of the sample header.
Definition Sample.h:218
nidas::util::Mutex _refLock
Definition Sample.h:369
void setSpSId(unsigned int val)
Set the short id portion of the sample header, containing the sensor + sample ids.
Definition Sample.h:236
Sample(sampleType t=CHAR_ST)
Definition Sample.h:193
virtual unsigned int getAllocLength() const =0
Get number of elements allocated in data portion of sample.
void holdReference() const
Increment the reference count for this sample.
Definition Sample.h:340
dsm_time_t getTimeTag() const
Time-tag in non-leap microseconds since Jan 1, 1970 00:00 GMT.
Definition Sample.h:206
virtual unsigned int getDataLength() const =0
Get the number of elements in data portion of sample.
void setTimeTag(dsm_time_t val)
Definition Sample.h:201
virtual const void * getConstVoidDataPtr() const =0
Get a const void* pointer to the data portion of the sample.
unsigned int getHeaderLength() const
Number of bytes in header.
Definition Sample.h:277
virtual void * getVoidDataPtr()=0
Get a void* pointer to the data portion of the sample.
virtual void setDataValue(unsigned int i, double val)=0
Set the value of data element i to a double.
unsigned int getDataByteLength() const
Get the number of bytes in data portion of sample.
Definition Sample.h:257
unsigned int getSpSId() const
Get the short id portion of the sample header.
Definition Sample.h:242
static int _nsamps
Global count of the number of samples in use by a process.
Definition Sample.h:378
void setId(dsm_sample_id_t val)
Set the id portion of the sample header.
Definition Sample.h:213
A class which wraps a numeric value and guards operations on it with a Mutex.
Definition MutexCount.h:40
A C++ wrapper for a POSIX mutex.
Definition ThreadSupport.h:161
void lock()
Lock the Mutex.
Definition ThreadSupport.h:216
void unlock()
Unlock the Mutex.
Definition ThreadSupport.h:230
char buffer[5000]
Definition loop.c:35
const float floatNAN
Value of a float NAN for general use.
Definition Sample.cc:31
unsigned int maxValue(unsigned short)
maxValue is an overloaded function returning the maximum value of its integer argument.
Definition sample_type_traits.h:10
const double doubleNAN
Definition Sample.cc:33
sampleType getSampleType(T *)
Definition sample_type_traits.h:111
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
sampleType
Definition sample_type_traits.h:30
@ CHAR_ST
Definition sample_type_traits.h:31
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:62
unsigned int dsm_sample_id_t
Definition Sample.h:64
Root namespace for the NCAR In-Situ Data Acquisition Software.
Definition A2DConverter.h:31
int len
Definition sing.cc:948
Definition sample_type_traits.h:46
unsigned int dsm_sample_length_t
length of data portion of sample.
Definition types.h:51