bufsize = count;
}
+ // FIXME: use realloc
void grow(size_t newsize)
{
if (newsize <= bufsize)
T *newptr = new(Alloc()) T[newsize];
memcpy(newptr, ptr, count * sizeof(T));
+ memset(newptr + count, 0, (newsize - count) * sizeof(T));
ptr = newptr;
ll_smp_membar_store_after_store();
Alloc::release(oldptr);
}
- // Caller must sync against all writers.
- void append(T *newptr, size_t len, size_t max = ULONG_MAX)
+ T *grow_by(size_t len, size_t max = ULONG_MAX)
{
+ size_t oldcount = count;
+
if (count + len < count)
throw ArrayException();
-
+
if (count + len > max)
throw ArrayException();
-
+
if (count + len > bufsize)
grow(ll_get_order_round_up(count + len));
-
- memcpy(ptr + count, newptr, len * sizeof(T));
+
+ return ptr + oldcount;
+ }
+
+ // align must be power-of-two
+ void align_to(size_t align, size_t max = ULONG_MAX)
+ {
+ size_t newcount = (count + align - 1) & ~(align - 1);
+
+ if (newcount < count)
+ throw ArrayException();
+
+ if (newcount > max)
+ throw ArrayException();
+
+ if (newcount > bufsize)
+ grow(ll_get_order_round_up(newcount));
+ }
+
+ // Caller must sync against all writers.
+ void append(T *newptr, size_t len, size_t max = ULONG_MAX)
+ {
+ memcpy(ptr + grow_by(len, max), newptr, len * sizeof(T));
count += len;
}
};