|
@@ -23,121 +23,73 @@
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
|
|
-// Simple BitSet // 0 based all, intermediate items exist, operations threadsafe and atomic
|
|
|
-
|
|
|
-class CBitSet : public CInterface, implements IBitSet
|
|
|
+// NB: The CBitSet* helpers are primarily avoid the need for virtuals in the implementations
|
|
|
+class CBitSetArrayHelper
|
|
|
{
|
|
|
-public:
|
|
|
- IMPLEMENT_IINTERFACE;
|
|
|
protected:
|
|
|
- //unsigned seems to be most efficient, and required for __builtin_ffs below
|
|
|
- typedef unsigned bits_t;
|
|
|
- enum { BitsPerItem = sizeof(bits_t) * 8 };
|
|
|
ArrayOf<bits_t> bits;
|
|
|
mutable CriticalSection crit;
|
|
|
|
|
|
-public:
|
|
|
- CBitSet() { }
|
|
|
- CBitSet(MemoryBuffer &buffer)
|
|
|
- {
|
|
|
- deserialize(buffer);
|
|
|
- }
|
|
|
- void set(unsigned n,bool val)
|
|
|
+ inline bits_t &getBitSet(unsigned i, bits_t &tmp) { tmp = bits.item(i); return tmp;}
|
|
|
+ inline void setBitSet(unsigned i, bits_t m)
|
|
|
{
|
|
|
- bits_t t=((bits_t)1)<<(n%BitsPerItem);
|
|
|
- unsigned i=n/BitsPerItem;
|
|
|
- CriticalBlock block(crit);
|
|
|
- if (i>=bits.ordinality()) {
|
|
|
- if (!val)
|
|
|
- return; // don't bother
|
|
|
- while (i>bits.ordinality())
|
|
|
- bits.append(0);
|
|
|
- bits.append(t);
|
|
|
- }
|
|
|
- else {
|
|
|
- bits_t m=bits.item(i);
|
|
|
- if (val)
|
|
|
- m |= t;
|
|
|
- else
|
|
|
- m &= ~t;
|
|
|
- bits.replace(m,i);
|
|
|
- }
|
|
|
+ bits.replace(m, i);
|
|
|
}
|
|
|
-
|
|
|
- bool invert(unsigned n)
|
|
|
+ inline void addBitSet(bits_t m)
|
|
|
{
|
|
|
- bits_t t=((bits_t)1)<<(n%BitsPerItem);
|
|
|
- unsigned i=n/BitsPerItem;
|
|
|
- CriticalBlock block(crit);
|
|
|
- bool ret;
|
|
|
- if (i>=bits.ordinality()) {
|
|
|
- while (i>bits.ordinality())
|
|
|
- bits.append(0);
|
|
|
- bits.append(t);
|
|
|
- ret = true;
|
|
|
- }
|
|
|
- else {
|
|
|
- bits_t m=bits.item(i);
|
|
|
- ret = ((m&t)==0);
|
|
|
- if (ret)
|
|
|
- m |= t;
|
|
|
- else
|
|
|
- m &= ~t;
|
|
|
- bits.replace(m,i);
|
|
|
- }
|
|
|
- return ret;
|
|
|
+ bits.append(m);
|
|
|
}
|
|
|
-
|
|
|
- bool test(unsigned n)
|
|
|
+ inline unsigned getWidth() const { return bits.ordinality(); }
|
|
|
+};
|
|
|
+
|
|
|
+class CBitSetMemoryHelper
|
|
|
+{
|
|
|
+protected:
|
|
|
+ bits_t *mem;
|
|
|
+ unsigned bitSetUnits;
|
|
|
+ MemoryBuffer mb; // Used if mem not provided, also implies expansion allowed
|
|
|
+ bool fixedMemory;
|
|
|
+
|
|
|
+ CBitSetMemoryHelper()
|
|
|
{
|
|
|
- bits_t t=((bits_t)1)<<(n%BitsPerItem);
|
|
|
- unsigned i=n/BitsPerItem;
|
|
|
- CriticalBlock block(crit);
|
|
|
- if (i<bits.ordinality()) {
|
|
|
- bits_t m=bits.item(i);
|
|
|
- if (m&t)
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
+ fixedMemory = false;
|
|
|
+ bitSetUnits = 0;
|
|
|
+ mem = NULL;
|
|
|
}
|
|
|
-
|
|
|
- bool testSet(unsigned n,bool val)
|
|
|
+ inline bits_t &getBitSet(unsigned i, bits_t &tmp) { return mem[i]; }
|
|
|
+ inline void setBitSet(unsigned i, bits_t m) { } // NOP, getBitset returns ref. in this impl. and the bits_t is set directly
|
|
|
+ inline void addBitSet(bits_t m)
|
|
|
{
|
|
|
- bits_t t=((bits_t)1)<<(n%BitsPerItem);
|
|
|
- unsigned i=n/BitsPerItem;
|
|
|
- CriticalBlock block(crit);
|
|
|
- bool ret;
|
|
|
- if (i>=bits.ordinality()) {
|
|
|
- ret = false;
|
|
|
- if (!val)
|
|
|
- return false; // don't bother
|
|
|
- while (i>bits.ordinality())
|
|
|
- bits.append(0);
|
|
|
- bits.append(t);
|
|
|
- }
|
|
|
- else {
|
|
|
- bits_t m=bits.item(i);
|
|
|
- ret = (m&t)!=0;
|
|
|
- if (val)
|
|
|
- m |= t;
|
|
|
- else
|
|
|
- m &= ~t;
|
|
|
- bits.replace(m,i);
|
|
|
- }
|
|
|
- return ret;
|
|
|
+ if (fixedMemory)
|
|
|
+ throw MakeStringException(-1, "CBitSetThreadUnsafe with fixed mem cannot expand");
|
|
|
+ mb.append(m);
|
|
|
+ mem = (bits_t *)mb.bufferBase();
|
|
|
+ ++bitSetUnits;
|
|
|
}
|
|
|
+ inline unsigned getWidth() const { return bitSetUnits; }
|
|
|
+};
|
|
|
+
|
|
|
+template <class BITSETHELPER>
|
|
|
+class CBitSetBase : public BITSETHELPER, public CSimpleInterfaceOf<IBitSet>
|
|
|
+{
|
|
|
+protected:
|
|
|
+ typedef BITSETHELPER PARENT;
|
|
|
+ using PARENT::getWidth;
|
|
|
+ using PARENT::getBitSet;
|
|
|
+ using PARENT::setBitSet;
|
|
|
+ using PARENT::addBitSet;
|
|
|
|
|
|
- unsigned _scan(unsigned from,bool tst,bool scninv)
|
|
|
+ unsigned _scan(unsigned from, bool tst, bool scninv)
|
|
|
{
|
|
|
bits_t noMatchMask=tst?0:(bits_t)-1;
|
|
|
unsigned j=from%BitsPerItem;
|
|
|
- CriticalBlock block(crit);
|
|
|
// returns index of first = val >= from
|
|
|
- unsigned n=bits.ordinality();
|
|
|
+ unsigned n=getWidth();
|
|
|
unsigned i;
|
|
|
+ bits_t tmpBitSet; // NB: for getBitSet, not all impls. will use it
|
|
|
for (i=from/BitsPerItem;i<n;i++)
|
|
|
{
|
|
|
- bits_t m=bits.item(i);
|
|
|
+ bits_t &m = getBitSet(i, tmpBitSet);
|
|
|
if (m!=noMatchMask)
|
|
|
{
|
|
|
#if defined(__GNUC__)
|
|
@@ -170,7 +122,7 @@ public:
|
|
|
{
|
|
|
bits_t t = ((bits_t)1)<<pos;
|
|
|
m &= ~t;
|
|
|
- bits.replace(m,i);
|
|
|
+ setBitSet(i, m);
|
|
|
}
|
|
|
return i*BitsPerItem+pos;
|
|
|
}
|
|
@@ -182,7 +134,7 @@ public:
|
|
|
{
|
|
|
bits_t t = ((bits_t)1)<<pos;
|
|
|
m |= t;
|
|
|
- bits.replace(m,i);
|
|
|
+ setBitSet(i, m);
|
|
|
}
|
|
|
return i*BitsPerItem+pos;
|
|
|
}
|
|
@@ -197,7 +149,7 @@ public:
|
|
|
if (scninv)
|
|
|
{
|
|
|
m &= ~t;
|
|
|
- bits.replace(m,i);
|
|
|
+ setBitSet(i, m);
|
|
|
}
|
|
|
return i*BitsPerItem+j;
|
|
|
}
|
|
@@ -209,7 +161,7 @@ public:
|
|
|
if (scninv)
|
|
|
{
|
|
|
m |= t;
|
|
|
- bits.replace(m,i);
|
|
|
+ setbitSet(i, m);
|
|
|
}
|
|
|
return i*BitsPerItem+j;
|
|
|
}
|
|
@@ -220,7 +172,7 @@ public:
|
|
|
}
|
|
|
j = 0;
|
|
|
}
|
|
|
- if (tst)
|
|
|
+ if (tst)
|
|
|
return (unsigned)-1;
|
|
|
unsigned ret = n*BitsPerItem;
|
|
|
if (n*BitsPerItem<from)
|
|
@@ -229,93 +181,198 @@ public:
|
|
|
set(ret,true);
|
|
|
return ret;
|
|
|
}
|
|
|
-
|
|
|
- unsigned scan(unsigned from,bool tst)
|
|
|
- {
|
|
|
- return _scan(from,tst,false);
|
|
|
- }
|
|
|
-
|
|
|
- unsigned scanInvert(unsigned from,bool tst) // like scan but inverts bit as well
|
|
|
- {
|
|
|
- return _scan(from,tst,true);
|
|
|
- }
|
|
|
-
|
|
|
- void _incl(unsigned lo, unsigned hi,bool val)
|
|
|
+ void _incl(unsigned lo, unsigned hi, bool val)
|
|
|
{
|
|
|
if (hi<lo)
|
|
|
return;
|
|
|
unsigned j=lo%BitsPerItem;
|
|
|
unsigned nb=(hi-lo)+1;
|
|
|
- CriticalBlock block(crit);
|
|
|
- unsigned n=bits.ordinality();
|
|
|
- unsigned i;
|
|
|
- for (i=lo/BitsPerItem;i<n;i++) {
|
|
|
- bits_t m;
|
|
|
- if ((nb>=BitsPerItem)&&(j==0)) {
|
|
|
- m = i;
|
|
|
- nb -= BitsPerItem;
|
|
|
+ unsigned n=getWidth();
|
|
|
+ unsigned i=lo/BitsPerItem;
|
|
|
+ if (n<=i)
|
|
|
+ {
|
|
|
+ if (val)
|
|
|
+ {
|
|
|
+ while (n < i)
|
|
|
+ {
|
|
|
+ addBitSet(0);
|
|
|
+ ++n;
|
|
|
+ }
|
|
|
}
|
|
|
- else {
|
|
|
- m=bits.item(i);
|
|
|
- bits_t t = ((bits_t)1)<<j;
|
|
|
- for (;j<BitsPerItem;j++) {
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bits_t tmpBitSet; // NB: for getBitSet, not all impls. will use it
|
|
|
+ for (;i<n;i++)
|
|
|
+ {
|
|
|
+ bits_t &m = getBitSet(i, tmpBitSet);
|
|
|
+ if ((nb>=BitsPerItem)&&(j==0))
|
|
|
+ {
|
|
|
if (val)
|
|
|
- m |= t;
|
|
|
+ m = (bits_t)-1;
|
|
|
else
|
|
|
- m &= ~t;
|
|
|
- if (--nb==0)
|
|
|
- break;
|
|
|
- t <<= 1;
|
|
|
+ m = 0;
|
|
|
+ nb -= BitsPerItem;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bits_t t = ((bits_t)1)<<j;
|
|
|
+ for (;j<BitsPerItem;j++)
|
|
|
+ {
|
|
|
+ if (val)
|
|
|
+ m |= t;
|
|
|
+ else
|
|
|
+ m &= ~t;
|
|
|
+ if (--nb==0)
|
|
|
+ break;
|
|
|
+ t <<= 1;
|
|
|
+ }
|
|
|
}
|
|
|
+ setBitSet(i, m);
|
|
|
+ if (nb==0)
|
|
|
+ return;
|
|
|
+ j = 0;
|
|
|
}
|
|
|
- bits.replace(m,i);
|
|
|
- if (nb==0)
|
|
|
- return;
|
|
|
- j = 0;
|
|
|
}
|
|
|
- if (val) {
|
|
|
- while (nb>=BitsPerItem) {
|
|
|
- bits.append((bits_t)-1);
|
|
|
- nb-=BitsPerItem;
|
|
|
+ if (val)
|
|
|
+ {
|
|
|
+ while (nb>=BitsPerItem)
|
|
|
+ {
|
|
|
+ addBitSet((bits_t)-1);
|
|
|
+ nb -= BitsPerItem;
|
|
|
}
|
|
|
- if (nb>0) {
|
|
|
+ if (nb>0)
|
|
|
+ {
|
|
|
bits_t m=0;
|
|
|
bits_t t = ((bits_t)1)<<j;
|
|
|
- for (;j<BitsPerItem;j++) {
|
|
|
+ for (;j<BitsPerItem;j++)
|
|
|
+ {
|
|
|
m |= t;
|
|
|
if (--nb==0)
|
|
|
break;
|
|
|
t <<= 1;
|
|
|
}
|
|
|
- bits.append(m);
|
|
|
+ addBitSet(m);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- void incl(unsigned lo, unsigned hi)
|
|
|
+public:
|
|
|
+// IBitSet impl.
|
|
|
+ virtual void set(unsigned n, bool val)
|
|
|
{
|
|
|
- _incl(lo,hi,true);
|
|
|
+ bits_t t=((bits_t)1)<<(n%BitsPerItem);
|
|
|
+ unsigned i = n/BitsPerItem;
|
|
|
+ if (i>=getWidth())
|
|
|
+ {
|
|
|
+ if (!val)
|
|
|
+ return; // don't bother
|
|
|
+ while (i>getWidth())
|
|
|
+ addBitSet(0);
|
|
|
+ addBitSet(t);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bits_t tmpBitSet; // NB: for getBitSet, not all impls. will use it
|
|
|
+ bits_t &m = getBitSet(i, tmpBitSet);
|
|
|
+ if (val)
|
|
|
+ m |= t;
|
|
|
+ else
|
|
|
+ m &= ~t;
|
|
|
+ setBitSet(i, m);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- void excl(unsigned lo, unsigned hi)
|
|
|
+ virtual bool invert(unsigned n)
|
|
|
{
|
|
|
- _incl(lo,hi,false);
|
|
|
+ bits_t t=((bits_t)1)<<(n%BitsPerItem);
|
|
|
+ unsigned i=n/BitsPerItem;
|
|
|
+ bool ret;
|
|
|
+ if (i>=getWidth())
|
|
|
+ {
|
|
|
+ while (i>getWidth())
|
|
|
+ addBitSet(0);
|
|
|
+ addBitSet(t);
|
|
|
+ ret = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bits_t tmpBitSet; // NB: for getBitSet, not all impls. will use it
|
|
|
+ bits_t &m = getBitSet(i, tmpBitSet);
|
|
|
+ ret = 0 == (m&t);
|
|
|
+ if (ret)
|
|
|
+ m |= t;
|
|
|
+ else
|
|
|
+ m &= ~t;
|
|
|
+ setBitSet(i, m);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
}
|
|
|
-
|
|
|
- void reset()
|
|
|
+ virtual bool test(unsigned n)
|
|
|
{
|
|
|
- CriticalBlock block(crit);
|
|
|
- bits.kill();
|
|
|
+ bits_t t=((bits_t)1)<<(n%BitsPerItem);
|
|
|
+ unsigned i=n/BitsPerItem;
|
|
|
+ if (i<getWidth())
|
|
|
+ {
|
|
|
+ bits_t tmpBitSet; // NB: for getBitSet, not all impls. will use it
|
|
|
+ bits_t &m = getBitSet(i, tmpBitSet);
|
|
|
+ if (m&t)
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
- void serialize(MemoryBuffer &buffer) const
|
|
|
+ virtual bool testSet(unsigned n, bool val)
|
|
|
{
|
|
|
- CriticalBlock block(crit);
|
|
|
- buffer.append(bits.ordinality());
|
|
|
- ForEachItemIn(b, bits)
|
|
|
- buffer.append(bits.item(b));
|
|
|
+ bits_t t=((bits_t)1)<<(n%BitsPerItem);
|
|
|
+ unsigned i=n/BitsPerItem;
|
|
|
+ bool ret;
|
|
|
+ if (i>=getWidth())
|
|
|
+ {
|
|
|
+ ret = false;
|
|
|
+ if (!val)
|
|
|
+ return false; // don't bother
|
|
|
+ while (i>getWidth())
|
|
|
+ addBitSet(0);
|
|
|
+ addBitSet(t);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bits_t tmpBitSet; // NB: for getBitSet, not all impls. will use it
|
|
|
+ bits_t &m = getBitSet(i, tmpBitSet);
|
|
|
+ ret = 0 != (m&t);
|
|
|
+ if (val)
|
|
|
+ m |= t;
|
|
|
+ else
|
|
|
+ m &= ~t;
|
|
|
+ setBitSet(i, m);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ virtual unsigned scan(unsigned from,bool tst)
|
|
|
+ {
|
|
|
+ return _scan(from,tst,false);
|
|
|
}
|
|
|
+ virtual unsigned scanInvert(unsigned from,bool tst) // like scan but inverts bit as well
|
|
|
+ {
|
|
|
+ return _scan(from,tst,true);
|
|
|
+ }
|
|
|
+ virtual void incl(unsigned lo, unsigned hi)
|
|
|
+ {
|
|
|
+ _incl(lo,hi,true);
|
|
|
+ }
|
|
|
+ virtual void excl(unsigned lo, unsigned hi)
|
|
|
+ {
|
|
|
+ _incl(lo,hi,false);
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
+size32_t getBitSetMemoryRequirement(unsigned numBits)
|
|
|
+{
|
|
|
+ unsigned bitSetUnits = (numBits + (BitsPerItem-1)) / BitsPerItem;
|
|
|
+ return bitSetUnits * sizeof(bits_t);
|
|
|
+}
|
|
|
+
|
|
|
+// Simple BitSet // 0 based all, intermediate items exist, operations threadsafe and atomic
|
|
|
+class CBitSet : public CBitSetBase<CBitSetArrayHelper>
|
|
|
+{
|
|
|
void deserialize(MemoryBuffer &buffer)
|
|
|
{
|
|
|
CriticalBlock block(crit);
|
|
@@ -333,6 +390,67 @@ public:
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+public:
|
|
|
+ CBitSet()
|
|
|
+ {
|
|
|
+ }
|
|
|
+ CBitSet(MemoryBuffer &buffer)
|
|
|
+ {
|
|
|
+ deserialize(buffer);
|
|
|
+ }
|
|
|
+// IBitSet overloads
|
|
|
+ virtual void set(unsigned n, bool val)
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ CBitSetBase::set(n, val);
|
|
|
+ }
|
|
|
+ virtual bool invert(unsigned n)
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ return CBitSetBase::invert(n);
|
|
|
+ }
|
|
|
+ virtual bool test(unsigned n)
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ return CBitSetBase::test(n);
|
|
|
+ }
|
|
|
+ virtual bool testSet(unsigned n, bool val)
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ return CBitSetBase::testSet(n, val);
|
|
|
+ }
|
|
|
+ virtual unsigned scan(unsigned from, bool tst)
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ return _scan(from,tst,false);
|
|
|
+ }
|
|
|
+ virtual unsigned scanInvert(unsigned from, bool tst) // like scan but inverts bit as well
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ return _scan(from,tst,true);
|
|
|
+ }
|
|
|
+ virtual void incl(unsigned lo, unsigned hi)
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ _incl(lo,hi,true);
|
|
|
+ }
|
|
|
+ virtual void excl(unsigned lo, unsigned hi)
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ _incl(lo,hi,false);
|
|
|
+ }
|
|
|
+ virtual void reset()
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ bits.kill();
|
|
|
+ }
|
|
|
+ virtual void serialize(MemoryBuffer &buffer) const
|
|
|
+ {
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ buffer.append(bits.ordinality());
|
|
|
+ ForEachItemIn(b, bits)
|
|
|
+ buffer.append(bits.item(b));
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
extern jlib_decl IBitSet *createBitSet()
|
|
@@ -340,10 +458,75 @@ extern jlib_decl IBitSet *createBitSet()
|
|
|
return new CBitSet();
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+class CBitSetThreadUnsafe : public CBitSetBase<CBitSetMemoryHelper>
|
|
|
+{
|
|
|
+ void deserialize(MemoryBuffer &buffer)
|
|
|
+ {
|
|
|
+ unsigned count;
|
|
|
+ buffer.read(count);
|
|
|
+ if (count)
|
|
|
+ {
|
|
|
+ unsigned bitSets = count/BitsPerItem;
|
|
|
+ bitSetUnits = bitSets;
|
|
|
+ mem = (bits_t *)mb.reserveTruncate(bitSets*sizeof(bits_t));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bitSetUnits = 0;
|
|
|
+ mem = NULL;
|
|
|
+ }
|
|
|
+ fixedMemory = false;
|
|
|
+ }
|
|
|
+public:
|
|
|
+ CBitSetThreadUnsafe()
|
|
|
+ {
|
|
|
+ // In this form, bitSetUnits and mem will be updated when addBitSet expands mb
|
|
|
+ }
|
|
|
+ CBitSetThreadUnsafe(size32_t memSz, const void *_mem, bool reset)
|
|
|
+ {
|
|
|
+ bitSetUnits = memSz*sizeof(byte) / sizeof(bits_t);
|
|
|
+ mem = (bits_t *)_mem;
|
|
|
+ if (reset)
|
|
|
+ memset(mem, 0, bitSetUnits*sizeof(bits_t));
|
|
|
+ fixedMemory = true;
|
|
|
+ }
|
|
|
+ CBitSetThreadUnsafe(MemoryBuffer &buffer)
|
|
|
+ {
|
|
|
+ deserialize(buffer);
|
|
|
+ }
|
|
|
+ virtual void reset()
|
|
|
+ {
|
|
|
+ memset(mem, 0, sizeof(bits_t)*bitSetUnits);
|
|
|
+ }
|
|
|
+ virtual void serialize(MemoryBuffer &buffer) const
|
|
|
+ {
|
|
|
+ buffer.append((unsigned)(BitsPerItem*bitSetUnits));
|
|
|
+ buffer.append(bitSetUnits*sizeof(bits_t), mem);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+extern jlib_decl IBitSet *createBitSetThreadUnsafe(unsigned maxBits, const void *mem, bool reset)
|
|
|
+{
|
|
|
+ return new CBitSetThreadUnsafe(maxBits, mem, reset);
|
|
|
+}
|
|
|
+
|
|
|
+extern jlib_decl IBitSet *createBitSetThreadUnsafe()
|
|
|
+{
|
|
|
+ return new CBitSetThreadUnsafe();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// NB: Doubt you'd want to interchange, but serialization formats are compatible
|
|
|
extern jlib_decl IBitSet *deserializeIBitSet(MemoryBuffer &mb)
|
|
|
{
|
|
|
return new CBitSet(mb);
|
|
|
}
|
|
|
|
|
|
+extern jlib_decl IBitSet *deserializeIBitSetThreadUnsafe(MemoryBuffer &mb)
|
|
|
+{
|
|
|
+ return new CBitSetThreadUnsafe(mb);
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|