Skip to content

Commit 1146b38

Browse files
committed
feat: unify constructors
1 parent 9b910d4 commit 1146b38

7 files changed

Lines changed: 65 additions & 97 deletions

File tree

cpp/pixels-retina/include/RGVisibility.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
template<size_t CAPACITY>
2727
class RGVisibility : public pixels::RetinaBase<RGVisibility<CAPACITY>> {
2828
public:
29-
explicit RGVisibility(uint64_t rgRecordNum);
30-
explicit RGVisibility(uint64_t rgRecordNum, uint64_t timestamp, const std::vector<uint64_t>& initialBitmap);
29+
explicit RGVisibility(uint64_t rgRecordNum, uint64_t timestamp = 0,
30+
const std::vector<uint64_t>* initialBitmap = nullptr);
3131
~RGVisibility() override;
3232

3333
void deleteRGRecord(uint32_t rowId, uint64_t timestamp);

cpp/pixels-retina/include/RGVisibilityJni.h

Lines changed: 1 addition & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cpp/pixels-retina/include/TileVisibility.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,13 @@ struct VersionedData : public pixels::RetinaBase<VersionedData<CAPACITY>> {
6565
uint64_t baseTimestamp;
6666
DeleteIndexBlock* head; // Delete chain head, part of the version
6767

68-
VersionedData() : baseTimestamp(0), head(nullptr) {
69-
std::memset(baseBitmap, 0, sizeof(baseBitmap));
70-
}
71-
72-
VersionedData(uint64_t ts, const uint64_t* bitmap, DeleteIndexBlock* h)
68+
// timestamp defaults to 0; bitmap defaults to all-zeros.
69+
explicit VersionedData(uint64_t ts = 0, const uint64_t* bitmap = nullptr, DeleteIndexBlock* h = nullptr)
7370
: baseTimestamp(ts), head(h) {
74-
std::memcpy(baseBitmap, bitmap, NUM_WORDS * sizeof(uint64_t));
71+
if (bitmap)
72+
std::memcpy(baseBitmap, bitmap, NUM_WORDS * sizeof(uint64_t));
73+
else
74+
std::memset(baseBitmap, 0, sizeof(baseBitmap));
7575
}
7676
};
7777

@@ -92,8 +92,8 @@ template<size_t CAPACITY>
9292
class TileVisibility : public pixels::RetinaBase<TileVisibility<CAPACITY>> {
9393
static constexpr size_t NUM_WORDS = BITMAP_WORDS(CAPACITY);
9494
public:
95-
TileVisibility();
96-
TileVisibility(uint64_t ts, const uint64_t* bitmap);
95+
// timestamp defaults to 0; bitmap defaults to all-zeros.
96+
explicit TileVisibility(uint64_t timestamp = 0, const uint64_t* bitmap = nullptr);
9797
~TileVisibility() override;
9898
void deleteTileRecord(uint16_t rowId, uint64_t ts);
9999
void getTileVisibilityBitmap(uint64_t ts, uint64_t* outBitmap) const;

cpp/pixels-retina/lib/RGVisibility.cpp

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,35 +22,23 @@
2222
#include <cstring>
2323
#include <thread>
2424

25+
// Validates before allocation: any throw leaves tileVisibilities as nullptr,
26+
// so the incomplete constructor does not invoke the destructor (no memory leak).
2527
template<size_t CAPACITY>
26-
RGVisibility<CAPACITY>::RGVisibility(uint64_t rgRecordNum)
27-
: tileCount((rgRecordNum + VISIBILITY_RECORD_CAPACITY - 1) / VISIBILITY_RECORD_CAPACITY) {
28-
size_t allocSize = tileCount * sizeof(TileVisibility<CAPACITY>);
29-
void* rawMemory = operator new[](allocSize);
30-
tileVisibilities = static_cast<TileVisibility<CAPACITY>*>(rawMemory);
31-
for (uint64_t i = 0; i < tileCount; ++i) {
32-
new (&tileVisibilities[i]) TileVisibility<CAPACITY>();
33-
}
34-
}
35-
36-
template<size_t CAPACITY>
37-
RGVisibility<CAPACITY>::RGVisibility(uint64_t rgRecordNum, uint64_t timestamp, const std::vector<uint64_t>& initialBitmap)
38-
: tileCount((rgRecordNum + VISIBILITY_RECORD_CAPACITY - 1) / VISIBILITY_RECORD_CAPACITY) {
39-
size_t allocSize = tileCount * sizeof(TileVisibility<CAPACITY>);
40-
void* rawMemory = operator new[](allocSize);
28+
RGVisibility<CAPACITY>::RGVisibility(uint64_t rgRecordNum, uint64_t timestamp,
29+
const std::vector<uint64_t>* initialBitmap)
30+
: tileCount((rgRecordNum + VISIBILITY_RECORD_CAPACITY - 1) / VISIBILITY_RECORD_CAPACITY),
31+
tileVisibilities(nullptr) {
32+
if (initialBitmap && initialBitmap->size() < tileCount * BITMAP_SIZE_PER_TILE_VISIBILITY)
33+
throw std::invalid_argument("Initial bitmap size is too small for the given record number.");
4134

42-
if (initialBitmap.size() < tileCount * BITMAP_SIZE_PER_TILE_VISIBILITY) {
43-
operator delete[](rawMemory);
44-
throw std::runtime_error("Initial bitmap size is too small for the given record number.");
45-
}
35+
tileVisibilities = static_cast<TileVisibility<CAPACITY>*>(
36+
operator new[](tileCount * sizeof(TileVisibility<CAPACITY>)));
4637

47-
tileVisibilities = static_cast<TileVisibility<CAPACITY>*>(rawMemory);
48-
for (uint64_t i = 0; i < tileCount; ++i) {
49-
// Each tile takes 4 uint64_t
50-
const uint64_t* tileBitmap = &initialBitmap[i * BITMAP_SIZE_PER_TILE_VISIBILITY];
51-
// We use timestamp 0 for restored checkpoints to serve as the base state
52-
new (&tileVisibilities[i]) TileVisibility<CAPACITY>(timestamp, tileBitmap);
53-
}
38+
for (uint64_t i = 0; i < tileCount; ++i)
39+
new (&tileVisibilities[i]) TileVisibility<CAPACITY>(
40+
timestamp,
41+
initialBitmap ? initialBitmap->data() + i * BITMAP_SIZE_PER_TILE_VISIBILITY : nullptr);
5442
}
5543

5644
template<size_t CAPACITY>

cpp/pixels-retina/lib/RGVisibilityJni.cpp

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,28 @@
2626
/*
2727
* Class: io_pixelsdb_pixels_retina_RGVisibility
2828
* Method: createNativeObject
29-
* Signature: (J)J
30-
*/
31-
JNIEXPORT jlong JNICALL Java_io_pixelsdb_pixels_retina_RGVisibility_createNativeObject
32-
(JNIEnv* env, jobject, jlong rgRecordNum) {
33-
try {
34-
auto* rgVisibility = new RGVisibilityInstance(rgRecordNum);
35-
return reinterpret_cast<jlong>(rgVisibility);
36-
} catch (const std::exception& e) {
37-
env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
38-
return 0;
39-
}
40-
}
41-
42-
/*
43-
* Class: io_pixelsdb_pixels_retina_RGVisibility
44-
* Method: createNativeObjectInitialized
4529
* Signature: (JJ[J)J
30+
*
31+
* Converts the Java bitmap array to a native vector when present, then
32+
* forwards to a single RGVisibility constructor call.
4633
*/
47-
JNIEXPORT jlong JNICALL Java_io_pixelsdb_pixels_retina_RGVisibility_createNativeObjectInitialized
34+
JNIEXPORT jlong JNICALL Java_io_pixelsdb_pixels_retina_RGVisibility_createNativeObject
4835
(JNIEnv* env, jobject, jlong rgRecordNum, jlong timestamp, jlongArray bitmap) {
4936
try {
50-
jsize len = env->GetArrayLength(bitmap);
51-
jlong *body = env->GetLongArrayElements(bitmap, nullptr);
52-
5337
std::vector<uint64_t> bitmapData;
54-
bitmapData.reserve(len);
55-
for (int i = 0; i < len; i++) {
56-
bitmapData.push_back((uint64_t)body[i]);
38+
const std::vector<uint64_t>* bitmapPtr = nullptr;
39+
if (bitmap != nullptr) {
40+
jsize len = env->GetArrayLength(bitmap);
41+
jlong* body = env->GetLongArrayElements(bitmap, nullptr);
42+
bitmapData.assign(reinterpret_cast<uint64_t*>(body),
43+
reinterpret_cast<uint64_t*>(body) + len);
44+
env->ReleaseLongArrayElements(bitmap, body, JNI_ABORT);
45+
bitmapPtr = &bitmapData;
5746
}
58-
59-
env->ReleaseLongArrayElements(bitmap, body, JNI_ABORT);
60-
61-
RGVisibilityInstance *rgVisibility = new RGVisibilityInstance(rgRecordNum, timestamp, bitmapData);
62-
return reinterpret_cast<jlong>(rgVisibility);
47+
return reinterpret_cast<jlong>(new RGVisibilityInstance(
48+
static_cast<uint64_t>(rgRecordNum),
49+
static_cast<uint64_t>(timestamp),
50+
bitmapPtr));
6351
} catch (const std::exception& e) {
6452
env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
6553
return 0;
@@ -195,6 +183,5 @@ JNIEXPORT jlong JNICALL Java_io_pixelsdb_pixels_retina_RGVisibility_getRetinaTra
195183
*/
196184
JNIEXPORT jlong JNICALL Java_io_pixelsdb_pixels_retina_RGVisibility_getRetinaObjectCount
197185
(JNIEnv *env, jclass clazz) {
198-
// Read the atomic object counter from RetinaBase namespace
199186
return static_cast<jlong>(pixels::g_retina_object_count.load(std::memory_order_relaxed));
200187
}

cpp/pixels-retina/lib/TileVisibility.cpp

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,9 @@
2727
#include <immintrin.h>
2828

2929
template<size_t CAPACITY>
30-
TileVisibility<CAPACITY>::TileVisibility() {
31-
VersionedData<CAPACITY>* initialVersion = new VersionedData<CAPACITY>();
32-
currentVersion.store(initialVersion, std::memory_order_release);
33-
tail.store(nullptr, std::memory_order_release);
34-
tailUsed.store(0, std::memory_order_release);
35-
}
36-
37-
template<size_t CAPACITY>
38-
TileVisibility<CAPACITY>::TileVisibility(uint64_t ts, const uint64_t* bitmap) {
39-
VersionedData<CAPACITY>* initialVersion = new VersionedData<CAPACITY>(ts, bitmap, nullptr);
40-
currentVersion.store(initialVersion, std::memory_order_release);
41-
tail.store(nullptr, std::memory_order_release);
42-
tailUsed.store(0, std::memory_order_release);
43-
}
30+
TileVisibility<CAPACITY>::TileVisibility(uint64_t timestamp, const uint64_t* bitmap)
31+
: currentVersion(new VersionedData<CAPACITY>(timestamp, bitmap)),
32+
tail(nullptr), tailUsed(0) {}
4433

4534
template<size_t CAPACITY>
4635
TileVisibility<CAPACITY>::~TileVisibility() {
@@ -392,4 +381,4 @@ void TileVisibility<CAPACITY>::reclaimRetiredVersions() {
392381
}
393382

394383
// Explicit Instantiations (Add the sizes you need here)
395-
template class TileVisibility<RETINA_CAPACITY>;
384+
template class TileVisibility<RETINA_CAPACITY>;

pixels-retina/src/main/java/io/pixelsdb/pixels/retina/RGVisibility.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,32 @@ public class RGVisibility implements AutoCloseable
6868
public RGVisibility(long rgRecordNum)
6969
{
7070
this.recordNum = rgRecordNum;
71-
this.nativeHandle.set(createNativeObject(rgRecordNum));
71+
this.nativeHandle.set(createNativeObject(rgRecordNum, 0L, null));
7272
}
7373

74-
public RGVisibility(long rgRecordNum, long timestamp, long[] initialBitmap)
74+
public RGVisibility(long rgRecordNum, long timestamp)
7575
{
76+
if (timestamp <= 0)
77+
{
78+
throw new IllegalArgumentException("timestamp must be positive when provided");
79+
}
7680
this.recordNum = rgRecordNum;
77-
if (initialBitmap == null)
81+
this.nativeHandle.set(createNativeObject(rgRecordNum, timestamp, null));
82+
}
83+
84+
public RGVisibility(long rgRecordNum, long timestamp, long[] initialBitmap)
85+
{
86+
if (timestamp <= 0)
7887
{
79-
this.nativeHandle.set(createNativeObject(rgRecordNum));
80-
} else
88+
throw new IllegalArgumentException("timestamp must be positive when provided");
89+
}
90+
91+
if (initialBitmap == null)
8192
{
82-
this.nativeHandle.set(createNativeObjectInitialized(rgRecordNum, timestamp, initialBitmap));
93+
throw new IllegalArgumentException("initial bitmap must not be null");
8394
}
95+
this.recordNum = rgRecordNum;
96+
this.nativeHandle.set(createNativeObject(rgRecordNum, timestamp, initialBitmap));
8497
}
8598

8699
public long getRecordNum()
@@ -99,8 +112,7 @@ public void close()
99112
}
100113

101114
// native methods
102-
private native long createNativeObject(long rgRecordNum);
103-
private native long createNativeObjectInitialized(long rgRecordNum, long timestamp, long[] bitmap);
115+
private native long createNativeObject(long rgRecordNum, long timestamp, long[] bitmap);
104116
private native void destroyNativeObject(long nativeHandle);
105117
private native void deleteRecord(int rgRowOffset, long timestamp, long nativeHandle);
106118
private native long[] getVisibilityBitmap(long timestamp, long nativeHandle);

0 commit comments

Comments
 (0)