kcdb.h | kcdb.h | |||
---|---|---|---|---|
skipping to change at line 795 | skipping to change at line 795 | |||
} | } | |||
std::string* key_; | std::string* key_; | |||
std::string* value_; | std::string* value_; | |||
bool ok_; | bool ok_; | |||
}; | }; | |||
VisitorImpl visitor(key, value); | VisitorImpl visitor(key, value); | |||
if (!accept(&visitor, false, step)) return false; | if (!accept(&visitor, false, step)) return false; | |||
return visitor.ok(); | return visitor.ok(); | |||
} | } | |||
/** | /** | |||
* Get a pair of the key and the value of the current record and remove | ||||
it atomically. | ||||
* @param ksp the pointer to the variable into which the size of the re | ||||
gion of the return | ||||
* value is assigned. | ||||
* @param vbp the pointer to the variable into which the pointer to the | ||||
value region is | ||||
* assigned. | ||||
* @param vsp the pointer to the variable into which the size of the va | ||||
lue region is | ||||
* assigned. | ||||
* @return the pointer to the key region, or NULL on failure. | ||||
* @note If the cursor is invalidated, NULL is returned. Because an ad | ||||
ditional zero code is | ||||
* appended at the end of each region of the key and the value, each re | ||||
gion can be treated | ||||
* as a C-style string. The return value should be deleted explicitly | ||||
by the caller with | ||||
* the detele[] operator. The cursor is moved to the next record impli | ||||
citly. | ||||
*/ | ||||
char* seize(size_t* ksp, const char** vbp, size_t* vsp) { | ||||
_assert_(ksp && vbp && vsp); | ||||
class VisitorImpl : public Visitor { | ||||
public: | ||||
explicit VisitorImpl() : kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_( | ||||
0) {} | ||||
char* pop(size_t* ksp, const char** vbp, size_t* vsp) { | ||||
*ksp = ksiz_; | ||||
*vbp = vbuf_; | ||||
*vsp = vsiz_; | ||||
return kbuf_; | ||||
} | ||||
void clear() { | ||||
delete[] kbuf_; | ||||
} | ||||
private: | ||||
const char* visit_full(const char* kbuf, size_t ksiz, | ||||
const char* vbuf, size_t vsiz, size_t* sp) { | ||||
size_t rsiz = ksiz + 1 + vsiz + 1; | ||||
kbuf_ = new char[rsiz]; | ||||
std::memcpy(kbuf_, kbuf, ksiz); | ||||
kbuf_[ksiz] = '\0'; | ||||
ksiz_ = ksiz; | ||||
vbuf_ = kbuf_ + ksiz + 1; | ||||
std::memcpy(vbuf_, vbuf, vsiz); | ||||
vbuf_[vsiz] = '\0'; | ||||
vsiz_ = vsiz; | ||||
return REMOVE; | ||||
} | ||||
char* kbuf_; | ||||
size_t ksiz_; | ||||
char* vbuf_; | ||||
size_t vsiz_; | ||||
}; | ||||
VisitorImpl visitor; | ||||
if (!accept(&visitor, true, false)) { | ||||
visitor.clear(); | ||||
*ksp = 0; | ||||
*vbp = NULL; | ||||
*vsp = 0; | ||||
return NULL; | ||||
} | ||||
return visitor.pop(ksp, vbp, vsp); | ||||
} | ||||
/** | ||||
* Get a pair of the key and the value of the current record and remove | ||||
it atomically. | ||||
* @note Equal to the original Cursor::seize method except that paramet | ||||
ers are strings | ||||
* to contain the result and the return value is bool for success. | ||||
*/ | ||||
bool seize(std::string* key, std::string* value) { | ||||
_assert_(key && value); | ||||
class VisitorImpl : public Visitor { | ||||
public: | ||||
explicit VisitorImpl(std::string* key, std::string* value) : | ||||
key_(key), value_(value), ok_(false) {} | ||||
bool ok() { | ||||
return ok_; | ||||
} | ||||
private: | ||||
const char* visit_full(const char* kbuf, size_t ksiz, | ||||
const char* vbuf, size_t vsiz, size_t* sp) { | ||||
key_->clear(); | ||||
key_->append(kbuf, ksiz); | ||||
value_->clear(); | ||||
value_->append(vbuf, vsiz); | ||||
ok_ = true; | ||||
return REMOVE; | ||||
} | ||||
std::string* key_; | ||||
std::string* value_; | ||||
bool ok_; | ||||
}; | ||||
VisitorImpl visitor(key, value); | ||||
if (!accept(&visitor, true, false)) return false; | ||||
return visitor.ok(); | ||||
} | ||||
/** | ||||
* Get the database object. | * Get the database object. | |||
* @return the database object. | * @return the database object. | |||
*/ | */ | |||
virtual BasicDB* db() = 0; | virtual BasicDB* db() = 0; | |||
/** | /** | |||
* Get the last happened error. | * Get the last happened error. | |||
* @return the last happened error. | * @return the last happened error. | |||
*/ | */ | |||
Error error() { | Error error() { | |||
_assert_(true); | _assert_(true); | |||
skipping to change at line 1846 | skipping to change at line 1935 | |||
return vbuf; | return vbuf; | |||
} | } | |||
/** | /** | |||
* Retrieve the value of a record. | * Retrieve the value of a record. | |||
* @note Equal to the original DB::get method except that the first param eters is the key | * @note Equal to the original DB::get method except that the first param eters is the key | |||
* string and the second parameter is a string to contain the result and the return value is | * string and the second parameter is a string to contain the result and the return value is | |||
* bool for success. | * bool for success. | |||
*/ | */ | |||
bool get(const std::string& key, std::string* value) { | bool get(const std::string& key, std::string* value) { | |||
_assert_(value); | _assert_(value); | |||
size_t vsiz; | class VisitorImpl : public Visitor { | |||
char* vbuf = get(key.c_str(), key.size(), &vsiz); | public: | |||
if (!vbuf) return false; | explicit VisitorImpl(std::string* value) : value_(value), ok_(false) | |||
value->clear(); | {} | |||
value->append(vbuf, vsiz); | bool ok() { | |||
delete[] vbuf; | return ok_; | |||
} | ||||
private: | ||||
const char* visit_full(const char* kbuf, size_t ksiz, | ||||
const char* vbuf, size_t vsiz, size_t* sp) { | ||||
value_->clear(); | ||||
value_->append(vbuf, vsiz); | ||||
ok_ = true; | ||||
return NOP; | ||||
} | ||||
std::string* value_; | ||||
bool ok_; | ||||
}; | ||||
VisitorImpl visitor(value); | ||||
if (!accept(key.data(), key.size(), &visitor, false)) return false; | ||||
if (!visitor.ok()) { | ||||
set_error(_KCCODELINE_, Error::NOREC, "no record"); | ||||
return false; | ||||
} | ||||
return true; | return true; | |||
} | } | |||
/** | /** | |||
* Retrieve the value of a record. | * Retrieve the value of a record. | |||
* @param kbuf the pointer to the key region. | * @param kbuf the pointer to the key region. | |||
* @param ksiz the size of the key region. | * @param ksiz the size of the key region. | |||
* @param vbuf the pointer to the buffer into which the value of the corr esponding record is | * @param vbuf the pointer to the buffer into which the value of the corr esponding record is | |||
* written. | * written. | |||
* @param max the size of the buffer. | * @param max the size of the buffer. | |||
* @return the size of the value, or -1 on failure. | * @return the size of the value, or -1 on failure. | |||
skipping to change at line 1893 | skipping to change at line 1999 | |||
VisitorImpl visitor(vbuf, max); | VisitorImpl visitor(vbuf, max); | |||
if (!accept(kbuf, ksiz, &visitor, false)) return -1; | if (!accept(kbuf, ksiz, &visitor, false)) return -1; | |||
int32_t vsiz = visitor.vsiz(); | int32_t vsiz = visitor.vsiz(); | |||
if (vsiz < 0) { | if (vsiz < 0) { | |||
set_error(_KCCODELINE_, Error::NOREC, "no record"); | set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
return -1; | return -1; | |||
} | } | |||
return vsiz; | return vsiz; | |||
} | } | |||
/** | /** | |||
* Retrieve the value of a record and remove it atomically. | ||||
* @param kbuf the pointer to the key region. | ||||
* @param ksiz the size of the key region. | ||||
* @param sp the pointer to the variable into which the size of the regio | ||||
n of the return | ||||
* value is assigned. | ||||
* @return the pointer to the value region of the corresponding record, o | ||||
r NULL on failure. | ||||
* @note If no record corresponds to the key, NULL is returned. Because | ||||
an additional zero | ||||
* code is appended at the end of the region of the return value, the ret | ||||
urn value can be | ||||
* treated as a C-style string. Because the region of the return value i | ||||
s allocated with the | ||||
* the new[] operator, it should be released with the delete[] operator w | ||||
hen it is no longer | ||||
* in use. | ||||
*/ | ||||
char* seize(const char* kbuf, size_t ksiz, size_t* sp) { | ||||
_assert_(kbuf && ksiz <= MEMMAXSIZ && sp); | ||||
class VisitorImpl : public Visitor { | ||||
public: | ||||
explicit VisitorImpl() : vbuf_(NULL), vsiz_(0) {} | ||||
char* pop(size_t* sp) { | ||||
*sp = vsiz_; | ||||
return vbuf_; | ||||
} | ||||
private: | ||||
const char* visit_full(const char* kbuf, size_t ksiz, | ||||
const char* vbuf, size_t vsiz, size_t* sp) { | ||||
vbuf_ = new char[vsiz+1]; | ||||
std::memcpy(vbuf_, vbuf, vsiz); | ||||
vbuf_[vsiz] = '\0'; | ||||
vsiz_ = vsiz; | ||||
return REMOVE; | ||||
} | ||||
char* vbuf_; | ||||
size_t vsiz_; | ||||
}; | ||||
VisitorImpl visitor; | ||||
if (!accept(kbuf, ksiz, &visitor, true)) { | ||||
*sp = 0; | ||||
return NULL; | ||||
} | ||||
size_t vsiz; | ||||
char* vbuf = visitor.pop(&vsiz); | ||||
if (!vbuf) { | ||||
set_error(_KCCODELINE_, Error::NOREC, "no record"); | ||||
*sp = 0; | ||||
return NULL; | ||||
} | ||||
*sp = vsiz; | ||||
return vbuf; | ||||
} | ||||
/** | ||||
* Retrieve the value of a record and remove it atomically. | ||||
* @note Equal to the original DB::seize method except that the first par | ||||
ameters is the key | ||||
* string and the second parameter is a string to contain the result and | ||||
the return value is | ||||
* bool for success. | ||||
*/ | ||||
bool seize(const std::string& key, std::string* value) { | ||||
_assert_(value); | ||||
class VisitorImpl : public Visitor { | ||||
public: | ||||
explicit VisitorImpl(std::string* value) : value_(value), ok_(false) | ||||
{} | ||||
bool ok() { | ||||
return ok_; | ||||
} | ||||
private: | ||||
const char* visit_full(const char* kbuf, size_t ksiz, | ||||
const char* vbuf, size_t vsiz, size_t* sp) { | ||||
value_->clear(); | ||||
value_->append(vbuf, vsiz); | ||||
ok_ = true; | ||||
return REMOVE; | ||||
} | ||||
std::string* value_; | ||||
bool ok_; | ||||
}; | ||||
VisitorImpl visitor(value); | ||||
if (!accept(key.data(), key.size(), &visitor, true)) return false; | ||||
if (!visitor.ok()) { | ||||
set_error(_KCCODELINE_, Error::NOREC, "no record"); | ||||
return false; | ||||
} | ||||
return true; | ||||
} | ||||
/** | ||||
* Store records at once. | * Store records at once. | |||
* @param recs the records to store. | * @param recs the records to store. | |||
* @param atomic true to perform all operations atomically, or false for non-atomic operations. | * @param atomic true to perform all operations atomically, or false for non-atomic operations. | |||
* @return the number of stored records, or -1 on failure. | * @return the number of stored records, or -1 on failure. | |||
*/ | */ | |||
int64_t set_bulk(const std::map<std::string, std::string>& recs, bool ato mic = true) { | int64_t set_bulk(const std::map<std::string, std::string>& recs, bool ato mic = true) { | |||
_assert_(true); | _assert_(true); | |||
if (atomic) { | if (atomic) { | |||
std::vector<std::string> keys; | std::vector<std::string> keys; | |||
keys.reserve(recs.size()); | keys.reserve(recs.size()); | |||
End of changes. 3 change blocks. | ||||
6 lines changed or deleted | 215 lines changed or added | |||
kclangc.h | kclangc.h | |||
---|---|---|---|---|
skipping to change at line 535 | skipping to change at line 535 | |||
* @param kbuf the pointer to the key region. | * @param kbuf the pointer to the key region. | |||
* @param ksiz the size of the key region. | * @param ksiz the size of the key region. | |||
* @param vbuf the pointer to the buffer into which the value of the corres ponding record is | * @param vbuf the pointer to the buffer into which the value of the corres ponding record is | |||
* written. | * written. | |||
* @param max the size of the buffer. | * @param max the size of the buffer. | |||
* @return the size of the value, or -1 on failure. | * @return the size of the value, or -1 on failure. | |||
*/ | */ | |||
int32_t kcdbgetbuf(KCDB* db, const char* kbuf, size_t ksiz, char* vbuf, siz e_t max); | int32_t kcdbgetbuf(KCDB* db, const char* kbuf, size_t ksiz, char* vbuf, siz e_t max); | |||
/** | /** | |||
* Retrieve the value of a record and remove it atomically. | ||||
* @param db a database object. | ||||
* @param kbuf the pointer to the key region. | ||||
* @param ksiz the size of the key region. | ||||
* @param sp the pointer to the variable into which the size of the region | ||||
of the return | ||||
* value is assigned. | ||||
* @return the pointer to the value region of the corresponding record, or | ||||
NULL on failure. | ||||
* @note If no record corresponds to the key, NULL is returned. Because an | ||||
additional zero | ||||
* code is appended at the end of the region of the return value, the retur | ||||
n value can be | ||||
* treated as a C-style string. The region of the return value should be r | ||||
eleased with the | ||||
* kcfree function when it is no longer in use. | ||||
*/ | ||||
char* kcdbseize(KCDB* db, const char* kbuf, size_t ksiz, size_t* sp); | ||||
/** | ||||
* Store records at once. | * Store records at once. | |||
* @param db a database object. | * @param db a database object. | |||
* @param recs the records to store. | * @param recs the records to store. | |||
* @param rnum specifies the number of the records. | * @param rnum specifies the number of the records. | |||
* @param atomic true to perform all operations atomically, or false for no n-atomic operations. | * @param atomic true to perform all operations atomically, or false for no n-atomic operations. | |||
* @return the number of stored records, or -1 on failure. | * @return the number of stored records, or -1 on failure. | |||
*/ | */ | |||
int64_t kcdbsetbulk(KCDB* db, const KCREC* recs, size_t rnum, int32_t atomi c); | int64_t kcdbsetbulk(KCDB* db, const KCREC* recs, size_t rnum, int32_t atomi c); | |||
/** | /** | |||
skipping to change at line 817 | skipping to change at line 832 | |||
* @param step true to move the cursor to the next record, or false for no move. | * @param step true to move the cursor to the next record, or false for no move. | |||
* @return the pointer to the pair of the key region, or NULL on failure. | * @return the pointer to the pair of the key region, or NULL on failure. | |||
* @note If the cursor is invalidated, NULL is returned. Because an additi onal zero code is | * @note If the cursor is invalidated, NULL is returned. Because an additi onal zero code is | |||
* appended at the end of each region of the key and the value, each region can be treated | * appended at the end of each region of the key and the value, each region can be treated | |||
* as a C-style string. The region of the return value should be released with the kcfree | * as a C-style string. The region of the return value should be released with the kcfree | |||
* function when it is no longer in use. | * function when it is no longer in use. | |||
*/ | */ | |||
char* kccurget(KCCUR* cur, size_t* ksp, const char** vbp, size_t* vsp, int3 2_t step); | char* kccurget(KCCUR* cur, size_t* ksp, const char** vbp, size_t* vsp, int3 2_t step); | |||
/** | /** | |||
* Get a pair of the key and the value of the current record and remove it | ||||
atomically. | ||||
* @param cur a cursor object. | ||||
* @param ksp the pointer to the variable into which the size of the region | ||||
of the return | ||||
* value is assigned. | ||||
* @param vbp the pointer to the variable into which the pointer to the val | ||||
ue region is | ||||
* assigned. | ||||
* @param vsp the pointer to the variable into which the size of the value | ||||
region is | ||||
* assigned. | ||||
* @return the pointer to the pair of the key region, or NULL on failure. | ||||
* @note If the cursor is invalidated, NULL is returned. Because an additi | ||||
onal zero code is | ||||
* appended at the end of each region of the key and the value, each region | ||||
can be treated | ||||
* as a C-style string. The region of the return value should be released | ||||
with the kcfree | ||||
* function when it is no longer in use. The cursor is moved to the next r | ||||
ecord implicitly. | ||||
*/ | ||||
char* kccurseize(KCCUR* cur, size_t* ksp, const char** vbp, size_t* vsp); | ||||
/** | ||||
* Jump the cursor to the first record for forward scan. | * Jump the cursor to the first record for forward scan. | |||
* @param cur a cursor object. | * @param cur a cursor object. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
int32_t kccurjump(KCCUR* cur); | int32_t kccurjump(KCCUR* cur); | |||
/** | /** | |||
* Jump the cursor to a record for forward scan. | * Jump the cursor to a record for forward scan. | |||
* @param cur a cursor object. | * @param cur a cursor object. | |||
* @param kbuf the pointer to the key region. | * @param kbuf the pointer to the key region. | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 45 lines changed or added | |||
kcplantdb.h | kcplantdb.h | |||
---|---|---|---|---|
skipping to change at line 123 | skipping to change at line 123 | |||
/** | /** | |||
* Cursor to indicate a record. | * Cursor to indicate a record. | |||
*/ | */ | |||
class Cursor : public BasicDB::Cursor { | class Cursor : public BasicDB::Cursor { | |||
friend class PlantDB; | friend class PlantDB; | |||
public: | public: | |||
/** | /** | |||
* Constructor. | * Constructor. | |||
* @param db the container database object. | * @param db the container database object. | |||
*/ | */ | |||
explicit Cursor(PlantDB* db) : db_(db), stack_(), kbuf_(NULL), ksiz_(0) | explicit Cursor(PlantDB* db) : | |||
, lid_(0) { | db_(db), stack_(), kbuf_(NULL), ksiz_(0), lid_(0), back_(false) { | |||
_assert_(db); | _assert_(db); | |||
ScopedRWLock lock(&db_->mlock_, true); | ScopedRWLock lock(&db_->mlock_, true); | |||
db_->curs_.push_back(this); | db_->curs_.push_back(this); | |||
} | } | |||
/** | /** | |||
* Destructor. | * Destructor. | |||
*/ | */ | |||
virtual ~Cursor() { | virtual ~Cursor() { | |||
_assert_(true); | _assert_(true); | |||
if (!db_) return; | if (!db_) return; | |||
skipping to change at line 206 | skipping to change at line 209 | |||
bool jump() { | bool jump() { | |||
_assert_(true); | _assert_(true); | |||
ScopedRWLock lock(&db_->mlock_, false); | ScopedRWLock lock(&db_->mlock_, false); | |||
if (db_->omode_ == 0) { | if (db_->omode_ == 0) { | |||
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |||
return false; | return false; | |||
} | } | |||
if (kbuf_) clear_position(); | if (kbuf_) clear_position(); | |||
bool err = false; | bool err = false; | |||
if (!set_position(db_->first_)) err = true; | if (!set_position(db_->first_)) err = true; | |||
back_ = false; | ||||
return !err; | return !err; | |||
} | } | |||
/** | /** | |||
* Jump the cursor to a record for forward scan. | * Jump the cursor to a record for forward scan. | |||
* @param kbuf the pointer to the key region. | * @param kbuf the pointer to the key region. | |||
* @param ksiz the size of the key region. | * @param ksiz the size of the key region. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
bool jump(const char* kbuf, size_t ksiz) { | bool jump(const char* kbuf, size_t ksiz) { | |||
_assert_(kbuf && ksiz <= MEMMAXSIZ); | _assert_(kbuf && ksiz <= MEMMAXSIZ); | |||
skipping to change at line 228 | skipping to change at line 232 | |||
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |||
return false; | return false; | |||
} | } | |||
if (kbuf_) clear_position(); | if (kbuf_) clear_position(); | |||
set_position(kbuf, ksiz, 0); | set_position(kbuf, ksiz, 0); | |||
bool err = false; | bool err = false; | |||
if (!adjust_position()) { | if (!adjust_position()) { | |||
if (kbuf_) clear_position(); | if (kbuf_) clear_position(); | |||
err = true; | err = true; | |||
} | } | |||
back_ = false; | ||||
return !err; | return !err; | |||
} | } | |||
/** | /** | |||
* Jump the cursor to a record for forward scan. | * Jump the cursor to a record for forward scan. | |||
* @note Equal to the original Cursor::jump method except that the para meter is std::string. | * @note Equal to the original Cursor::jump method except that the para meter is std::string. | |||
*/ | */ | |||
bool jump(const std::string& key) { | bool jump(const std::string& key) { | |||
_assert_(true); | _assert_(true); | |||
return jump(key.c_str(), key.size()); | return jump(key.c_str(), key.size()); | |||
} | } | |||
skipping to change at line 254 | skipping to change at line 259 | |||
bool jump_back() { | bool jump_back() { | |||
_assert_(true); | _assert_(true); | |||
ScopedRWLock lock(&db_->mlock_, false); | ScopedRWLock lock(&db_->mlock_, false); | |||
if (db_->omode_ == 0) { | if (db_->omode_ == 0) { | |||
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |||
return false; | return false; | |||
} | } | |||
if (kbuf_) clear_position(); | if (kbuf_) clear_position(); | |||
bool err = false; | bool err = false; | |||
if (!set_position_back(db_->last_)) err = true; | if (!set_position_back(db_->last_)) err = true; | |||
back_ = true; | ||||
return !err; | return !err; | |||
} | } | |||
/** | /** | |||
* Jump the cursor to a record for backward scan. | * Jump the cursor to a record for backward scan. | |||
* @param kbuf the pointer to the key region. | * @param kbuf the pointer to the key region. | |||
* @param ksiz the size of the key region. | * @param ksiz the size of the key region. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
bool jump_back(const char* kbuf, size_t ksiz) { | bool jump_back(const char* kbuf, size_t ksiz) { | |||
_assert_(kbuf && ksiz <= MEMMAXSIZ); | _assert_(kbuf && ksiz <= MEMMAXSIZ); | |||
skipping to change at line 291 | skipping to change at line 297 | |||
} else { | } else { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
err = true; | err = true; | |||
} | } | |||
} | } | |||
} | } | |||
} else { | } else { | |||
if (kbuf_) clear_position(); | if (kbuf_) clear_position(); | |||
if (!set_position_back(db_->last_)) err = true; | if (!set_position_back(db_->last_)) err = true; | |||
} | } | |||
back_ = true; | ||||
return !err; | return !err; | |||
} | } | |||
/** | /** | |||
* Jump the cursor to a record for backward scan. | * Jump the cursor to a record for backward scan. | |||
* @note Equal to the original Cursor::jump_back method except that the parameter is | * @note Equal to the original Cursor::jump_back method except that the parameter is | |||
* std::string. | * std::string. | |||
*/ | */ | |||
bool jump_back(const std::string& key) { | bool jump_back(const std::string& key) { | |||
_assert_(true); | _assert_(true); | |||
return jump_back(key.c_str(), key.size()); | return jump_back(key.c_str(), key.size()); | |||
skipping to change at line 314 | skipping to change at line 321 | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
bool step() { | bool step() { | |||
_assert_(true); | _assert_(true); | |||
DB::Visitor visitor; | DB::Visitor visitor; | |||
if (!accept(&visitor, false, true)) return false; | if (!accept(&visitor, false, true)) return false; | |||
if (!kbuf_) { | if (!kbuf_) { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
return false; | return false; | |||
} | } | |||
back_ = false; | ||||
return true; | return true; | |||
} | } | |||
/** | /** | |||
* Step the cursor to the previous record. | * Step the cursor to the previous record. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
bool step_back() { | bool step_back() { | |||
_assert_(true); | _assert_(true); | |||
db_->mlock_.lock_reader(); | db_->mlock_.lock_reader(); | |||
if (db_->omode_ == 0) { | if (db_->omode_ == 0) { | |||
skipping to change at line 347 | skipping to change at line 355 | |||
db_->mlock_.unlock(); | db_->mlock_.unlock(); | |||
db_->mlock_.lock_writer(); | db_->mlock_.lock_writer(); | |||
if (kbuf_) { | if (kbuf_) { | |||
if (!back_position_atom()) err = true; | if (!back_position_atom()) err = true; | |||
} else { | } else { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
err = true; | err = true; | |||
} | } | |||
} | } | |||
db_->mlock_.unlock(); | db_->mlock_.unlock(); | |||
back_ = true; | ||||
return !err; | return !err; | |||
} | } | |||
/** | /** | |||
* Get the database object. | * Get the database object. | |||
* @return the database object. | * @return the database object. | |||
*/ | */ | |||
PlantDB* db() { | PlantDB* db() { | |||
_assert_(true); | _assert_(true); | |||
return db_; | return db_; | |||
} | } | |||
skipping to change at line 516 | skipping to change at line 525 | |||
node->dirty = true; | node->dirty = true; | |||
if (recs.size() <= 1) { | if (recs.size() <= 1) { | |||
lsiz = sizeof(Link) + ksiz; | lsiz = sizeof(Link) + ksiz; | |||
lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |||
link = (Link*)lbuf; | link = (Link*)lbuf; | |||
link->child = 0; | link->child = 0; | |||
link->ksiz = ksiz; | link->ksiz = ksiz; | |||
std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | |||
} | } | |||
xfree(rec); | xfree(rec); | |||
typename RecordArray::iterator ritnext = rit + 1; | if (back_) { | |||
if (ritnext != ritend) { | if (rit == recs.begin()) { | |||
clear_position(); | step = true; | |||
set_position(*ritnext, node->id); | } else { | |||
step = false; | typename RecordArray::iterator ritprev = rit - 1; | |||
set_position(*ritprev, node->id); | ||||
step = false; | ||||
} | ||||
} else { | ||||
typename RecordArray::iterator ritnext = rit + 1; | ||||
if (ritnext == ritend) { | ||||
step = true; | ||||
} else { | ||||
clear_position(); | ||||
set_position(*ritnext, node->id); | ||||
step = false; | ||||
} | ||||
} | } | |||
recs.erase(rit); | recs.erase(rit); | |||
} else if (vbuf != Visitor::NOP) { | } else if (vbuf != Visitor::NOP) { | |||
int64_t diff = (int64_t)vsiz - (int64_t)rec->vsiz; | int64_t diff = (int64_t)vsiz - (int64_t)rec->vsiz; | |||
db_->cusage_ += diff; | db_->cusage_ += diff; | |||
node->size += diff; | node->size += diff; | |||
node->dirty = true; | node->dirty = true; | |||
if (vsiz > rec->vsiz) { | if (vsiz > rec->vsiz) { | |||
*rit = (Record*)xrealloc(rec, sizeof(*rec) + rec->ksiz + vsiz); | *rit = (Record*)xrealloc(rec, sizeof(*rec) + rec->ksiz + vsiz); | |||
rec = *rit; | rec = *rit; | |||
skipping to change at line 545 | skipping to change at line 566 | |||
if (node->size > db_->psiz_ && recs.size() > 1) { | if (node->size > db_->psiz_ && recs.size() > 1) { | |||
lsiz = sizeof(Link) + ksiz; | lsiz = sizeof(Link) + ksiz; | |||
lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | lbuf = lsiz > sizeof(lstack) ? new char[lsiz] : lstack; | |||
link = (Link*)lbuf; | link = (Link*)lbuf; | |||
link->child = 0; | link->child = 0; | |||
link->ksiz = ksiz; | link->ksiz = ksiz; | |||
std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | std::memcpy(lbuf + sizeof(*link), kbuf, ksiz); | |||
} | } | |||
} | } | |||
if (step) { | if (step) { | |||
++rit; | if (back_) { | |||
if (rit != ritend) { | if (rit != recs.begin()) { | |||
clear_position(); | --rit; | |||
set_position(*rit, node->id); | set_position(*rit, node->id); | |||
step = false; | step = false; | |||
} | ||||
} else { | ||||
++rit; | ||||
if (rit != ritend) { | ||||
clear_position(); | ||||
set_position(*rit, node->id); | ||||
step = false; | ||||
} | ||||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
bool atran = db_->autotran_ && !db_->tran_ && node->dirty; | bool atran = db_->autotran_ && !db_->tran_ && node->dirty; | |||
bool async = db_->autosync_ && !db_->autotran_ && !db_->tran_ && no de->dirty; | bool async = db_->autosync_ && !db_->autotran_ && !db_->tran_ && no de->dirty; | |||
node->lock.unlock(); | node->lock.unlock(); | |||
if (hit && step) { | if (hit && step) { | |||
clear_position(); | clear_position(); | |||
set_position(node->next); | if (back_) { | |||
set_position_back(node->prev); | ||||
} else { | ||||
set_position(node->next); | ||||
} | ||||
} | } | |||
if (hit) { | if (hit) { | |||
bool flush = db_->cusage_ > db_->pccap_; | bool flush = db_->cusage_ > db_->pccap_; | |||
if (link || flush || async) { | if (link || flush || async) { | |||
int64_t id = node->id; | int64_t id = node->id; | |||
if (atran && !link && !db_->fix_auto_transaction_leaf(node)) er r = true; | if (atran && !link && !db_->fix_auto_transaction_leaf(node)) er r = true; | |||
db_->mlock_.unlock(); | db_->mlock_.unlock(); | |||
db_->mlock_.lock_writer(); | db_->mlock_.lock_writer(); | |||
if (link) { | if (link) { | |||
node = db_->search_tree(link, true, hist, &hnum); | node = db_->search_tree(link, true, hist, &hnum); | |||
skipping to change at line 682 | skipping to change at line 715 | |||
size_t vsiz; | size_t vsiz; | |||
const char* vbuf = visitor->visit_full(kbuf, ksiz, kbuf + ksiz, | const char* vbuf = visitor->visit_full(kbuf, ksiz, kbuf + ksiz, | |||
rec->vsiz, &vsiz); | rec->vsiz, &vsiz); | |||
if (vbuf == Visitor::REMOVE) { | if (vbuf == Visitor::REMOVE) { | |||
rsiz = sizeof(*rec) + rec->ksiz + rec->vsiz; | rsiz = sizeof(*rec) + rec->ksiz + rec->vsiz; | |||
db_->count_ -= 1; | db_->count_ -= 1; | |||
db_->cusage_ -= rsiz; | db_->cusage_ -= rsiz; | |||
node->size -= rsiz; | node->size -= rsiz; | |||
node->dirty = true; | node->dirty = true; | |||
xfree(rec); | xfree(rec); | |||
typename RecordArray::iterator ritnext = rit + 1; | step = false; | |||
if (ritnext != ritend) { | clear_position(); | |||
clear_position(); | if (back_) { | |||
set_position(*ritnext, node->id); | if (rit == recs.begin()) { | |||
step = false; | set_position_back(node->prev); | |||
} else { | ||||
typename RecordArray::iterator ritprev = rit - 1; | ||||
set_position(*ritprev, node->id); | ||||
} | ||||
} else { | ||||
typename RecordArray::iterator ritnext = rit + 1; | ||||
if (ritnext == ritend) { | ||||
set_position(node->next); | ||||
} else { | ||||
set_position(*ritnext, node->id); | ||||
} | ||||
} | } | |||
recs.erase(rit); | recs.erase(rit); | |||
if (recs.empty()) reorg = true; | if (recs.empty()) reorg = true; | |||
} else if (vbuf != Visitor::NOP) { | } else if (vbuf != Visitor::NOP) { | |||
int64_t diff = (int64_t)vsiz - (int64_t)rec->vsiz; | int64_t diff = (int64_t)vsiz - (int64_t)rec->vsiz; | |||
db_->cusage_ += diff; | db_->cusage_ += diff; | |||
node->size += diff; | node->size += diff; | |||
node->dirty = true; | node->dirty = true; | |||
if (vsiz > rec->vsiz) { | if (vsiz > rec->vsiz) { | |||
*rit = (Record*)xrealloc(rec, sizeof(*rec) + rec->ksiz + vsiz); | *rit = (Record*)xrealloc(rec, sizeof(*rec) + rec->ksiz + vsiz); | |||
rec = *rit; | rec = *rit; | |||
kbuf = (char*)rec + sizeof(*rec); | kbuf = (char*)rec + sizeof(*rec); | |||
} | } | |||
std::memcpy(kbuf + rec->ksiz, vbuf, vsiz); | std::memcpy(kbuf + rec->ksiz, vbuf, vsiz); | |||
rec->vsiz = vsiz; | rec->vsiz = vsiz; | |||
if (node->size > db_->psiz_ && recs.size() > 1) reorg = true; | if (node->size > db_->psiz_ && recs.size() > 1) reorg = true; | |||
} | } | |||
if (step) { | if (step) { | |||
++rit; | clear_position(); | |||
if (rit != ritend) { | if (back_) { | |||
clear_position(); | if (rit == recs.begin()) { | |||
set_position(*rit, node->id); | set_position_back(node->prev); | |||
} else { | ||||
--rit; | ||||
set_position(*rit, node->id); | ||||
} | ||||
} else { | } else { | |||
clear_position(); | ++rit; | |||
set_position(node->next); | if (rit == ritend) { | |||
set_position(node->next); | ||||
} else { | ||||
set_position(*rit, node->id); | ||||
} | ||||
} | } | |||
} | } | |||
bool atran = db_->autotran_ && !db_->tran_ && node->dirty; | bool atran = db_->autotran_ && !db_->tran_ && node->dirty; | |||
bool async = db_->autosync_ && !db_->autotran_ && !db_->tran_ && no de->dirty; | bool async = db_->autosync_ && !db_->autotran_ && !db_->tran_ && no de->dirty; | |||
if (atran && !reorg && !db_->fix_auto_transaction_leaf(node)) err = true; | if (atran && !reorg && !db_->fix_auto_transaction_leaf(node)) err = true; | |||
if (reorg) { | if (reorg) { | |||
if (!db_->reorganize_tree(node, hist, hnum)) err = true; | if (!db_->reorganize_tree(node, hist, hnum)) err = true; | |||
if (atran && !db_->fix_auto_transaction_tree()) err = true; | if (atran && !db_->fix_auto_transaction_tree()) err = true; | |||
} else if (db_->cusage_ > db_->pccap_) { | } else if (db_->cusage_ > db_->pccap_) { | |||
int32_t idx = node->id % SLOTNUM; | int32_t idx = node->id % SLOTNUM; | |||
LeafSlot* lslot = db_->lslots_ + idx; | LeafSlot* lslot = db_->lslots_ + idx; | |||
if (!db_->flush_leaf_cache_part(lslot)) err = true; | if (!db_->flush_leaf_cache_part(lslot)) err = true; | |||
InnerSlot* islot = db_->islots_ + idx; | InnerSlot* islot = db_->islots_ + idx; | |||
if (islot->warm->count() > lslot->warm->count() + lslot->hot->cou nt() + 1 && | if (islot->warm->count() > lslot->warm->count() + lslot->hot->cou nt() + 1 && | |||
!db_->flush_inner_cache_part(islot)) err = true; | !db_->flush_inner_cache_part(islot)) err = true; | |||
} | } | |||
if (async && !db_->fix_auto_synchronization()) err = true; | if (async && !db_->fix_auto_synchronization()) err = true; | |||
} else { | } else { | |||
int64_t lid = lid_; | int64_t lid = lid_; | |||
clear_position(); | clear_position(); | |||
if (set_position(node->next)) { | if (back_) { | |||
if (lid_ == lid) { | if (set_position_back(node->prev)) { | |||
db_->set_error(_KCCODELINE_, Error::BROKEN, "invalid leaf node" | if (lid_ == lid) { | |||
); | db_->set_error(_KCCODELINE_, Error::BROKEN, "invalid leaf nod | |||
err = true; | e"); | |||
err = true; | ||||
} else { | ||||
*retryp = true; | ||||
} | ||||
} else { | } else { | |||
*retryp = true; | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
err = true; | ||||
} | } | |||
} else { | } else { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | if (set_position(node->next)) { | |||
err = true; | if (lid_ == lid) { | |||
db_->set_error(_KCCODELINE_, Error::BROKEN, "invalid leaf nod | ||||
e"); | ||||
err = true; | ||||
} else { | ||||
*retryp = true; | ||||
} | ||||
} else { | ||||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | ||||
err = true; | ||||
} | ||||
} | } | |||
} | } | |||
if (rbuf != rstack) delete[] rbuf; | if (rbuf != rstack) delete[] rbuf; | |||
if (lbuf != lstack) delete[] lbuf; | if (lbuf != lstack) delete[] lbuf; | |||
return !err; | return !err; | |||
} | } | |||
/** | /** | |||
* Adjust the position to an existing record. | * Adjust the position to an existing record. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
skipping to change at line 914 | skipping to change at line 980 | |||
/** The inner database. */ | /** The inner database. */ | |||
PlantDB* db_; | PlantDB* db_; | |||
/** The stack buffer for the key. */ | /** The stack buffer for the key. */ | |||
char stack_[KCPDRECBUFSIZ]; | char stack_[KCPDRECBUFSIZ]; | |||
/** The pointer to the key region. */ | /** The pointer to the key region. */ | |||
char* kbuf_; | char* kbuf_; | |||
/** The size of the key region. */ | /** The size of the key region. */ | |||
size_t ksiz_; | size_t ksiz_; | |||
/** The last visited leaf. */ | /** The last visited leaf. */ | |||
int64_t lid_; | int64_t lid_; | |||
/** The backward flag. */ | ||||
bool back_; | ||||
}; | }; | |||
/** | /** | |||
* Tuning options. | * Tuning options. | |||
*/ | */ | |||
enum Option { | enum Option { | |||
TSMALL = BASEDB::TSMALL, ///< use 32-bit addressing | TSMALL = BASEDB::TSMALL, ///< use 32-bit addressing | |||
TLINEAR = BASEDB::TLINEAR, ///< use linear collision chaining | TLINEAR = BASEDB::TLINEAR, ///< use linear collision chaining | |||
TCOMPRESS = BASEDB::TCOMPRESS ///< compress each record | TCOMPRESS = BASEDB::TCOMPRESS ///< compress each record | |||
}; | }; | |||
/** | /** | |||
End of changes. 17 change blocks. | ||||
32 lines changed or deleted | 98 lines changed or added | |||
kcprotodb.h | kcprotodb.h | |||
---|---|---|---|---|
skipping to change at line 126 | skipping to change at line 126 | |||
if (db_->tran_) { | if (db_->tran_) { | |||
TranLog log(key, value); | TranLog log(key, value); | |||
db_->trlogs_.push_back(log); | db_->trlogs_.push_back(log); | |||
} | } | |||
db_->size_ -= key.size() + value.size(); | db_->size_ -= key.size() + value.size(); | |||
if (db_->curs_.size() > 1) { | if (db_->curs_.size() > 1) { | |||
typename CursorList::const_iterator cit = db_->curs_.begin(); | typename CursorList::const_iterator cit = db_->curs_.begin(); | |||
typename CursorList::const_iterator citend = db_->curs_.end(); | typename CursorList::const_iterator citend = db_->curs_.end(); | |||
while (cit != citend) { | while (cit != citend) { | |||
Cursor* cur = *cit; | Cursor* cur = *cit; | |||
if (cur != this && cur->it_ == it_) cur->it_++; | if (cur != this && cur->it_ == it_) ++cur->it_; | |||
++cit; | ++cit; | |||
} | } | |||
} | } | |||
db_->recs_.erase(it_++); | db_->recs_.erase(it_++); | |||
} else if (vbuf == Visitor::NOP) { | } else if (vbuf == Visitor::NOP) { | |||
if (step) it_++; | if (step) ++it_; | |||
} else { | } else { | |||
if (db_->tran_) { | if (db_->tran_) { | |||
TranLog log(key, value); | TranLog log(key, value); | |||
db_->trlogs_.push_back(log); | db_->trlogs_.push_back(log); | |||
} | } | |||
db_->size_ -= value.size(); | db_->size_ -= value.size(); | |||
db_->size_ += vsiz; | db_->size_ += vsiz; | |||
it_->second = std::string(vbuf, vsiz); | it_->second = std::string(vbuf, vsiz); | |||
if (step) it_++; | if (step) ++it_; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
/** | /** | |||
* Jump the cursor to the first record for forward scan. | * Jump the cursor to the first record for forward scan. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
bool jump() { | bool jump() { | |||
_assert_(true); | _assert_(true); | |||
ScopedRWLock lock(&db_->mlock_, true); | ScopedRWLock lock(&db_->mlock_, true); | |||
skipping to change at line 279 | skipping to change at line 279 | |||
_assert_(true); | _assert_(true); | |||
ScopedRWLock lock(&db_->mlock_, true); | ScopedRWLock lock(&db_->mlock_, true); | |||
if (db_->omode_ == 0) { | if (db_->omode_ == 0) { | |||
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |||
return false; | return false; | |||
} | } | |||
if (it_ == db_->recs_.end()) { | if (it_ == db_->recs_.end()) { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
return false; | return false; | |||
} | } | |||
it_++; | ++it_; | |||
if (it_ == db_->recs_.end()) { | if (it_ == db_->recs_.end()) { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
return false; | return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
/** | /** | |||
* Step the cursor to the previous record. | * Step the cursor to the previous record. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
skipping to change at line 414 | skipping to change at line 414 | |||
if (tran_) { | if (tran_) { | |||
TranLog log(key, value); | TranLog log(key, value); | |||
trlogs_.push_back(log); | trlogs_.push_back(log); | |||
} | } | |||
size_ -= ksiz + value.size(); | size_ -= ksiz + value.size(); | |||
if (!curs_.empty()) { | if (!curs_.empty()) { | |||
typename CursorList::const_iterator cit = curs_.begin(); | typename CursorList::const_iterator cit = curs_.begin(); | |||
typename CursorList::const_iterator citend = curs_.end(); | typename CursorList::const_iterator citend = curs_.end(); | |||
while (cit != citend) { | while (cit != citend) { | |||
Cursor* cur = *cit; | Cursor* cur = *cit; | |||
if (cur->it_ == it) cur->it_++; | if (cur->it_ == it) ++cur->it_; | |||
++cit; | ++cit; | |||
} | } | |||
} | } | |||
recs_.erase(it); | recs_.erase(it); | |||
} else if (vbuf != Visitor::NOP) { | } else if (vbuf != Visitor::NOP) { | |||
if (tran_) { | if (tran_) { | |||
TranLog log(key, value); | TranLog log(key, value); | |||
trlogs_.push_back(log); | trlogs_.push_back(log); | |||
} | } | |||
size_ -= value.size(); | size_ -= value.size(); | |||
skipping to change at line 513 | skipping to change at line 513 | |||
if (tran_) { | if (tran_) { | |||
TranLog log(key, value); | TranLog log(key, value); | |||
trlogs_.push_back(log); | trlogs_.push_back(log); | |||
} | } | |||
size_ -= key.size() + value.size(); | size_ -= key.size() + value.size(); | |||
if (!curs_.empty()) { | if (!curs_.empty()) { | |||
typename CursorList::const_iterator cit = curs_.begin(); | typename CursorList::const_iterator cit = curs_.begin(); | |||
typename CursorList::const_iterator citend = curs_.end(); | typename CursorList::const_iterator citend = curs_.end(); | |||
while (cit != citend) { | while (cit != citend) { | |||
Cursor* cur = *cit; | Cursor* cur = *cit; | |||
if (cur->it_ == it) cur->it_++; | if (cur->it_ == it) ++cur->it_; | |||
++cit; | ++cit; | |||
} | } | |||
} | } | |||
recs_.erase(it); | recs_.erase(it); | |||
} else if (vbuf != Visitor::NOP) { | } else if (vbuf != Visitor::NOP) { | |||
if (tran_) { | if (tran_) { | |||
TranLog log(key, value); | TranLog log(key, value); | |||
trlogs_.push_back(log); | trlogs_.push_back(log); | |||
} | } | |||
size_ -= value.size(); | size_ -= value.size(); | |||
End of changes. 6 change blocks. | ||||
6 lines changed or deleted | 6 lines changed or added | |||
kcthread.h | kcthread.h | |||
---|---|---|---|---|
skipping to change at line 1068 | skipping to change at line 1068 | |||
/** | /** | |||
* Destructor. | * Destructor. | |||
*/ | */ | |||
virtual ~Task() { | virtual ~Task() { | |||
_assert_(true); | _assert_(true); | |||
} | } | |||
/** | /** | |||
* Get the ID number of the task. | * Get the ID number of the task. | |||
* @return the ID number of the task, which is incremented from 1. | * @return the ID number of the task, which is incremented from 1. | |||
*/ | */ | |||
uint64_t id() { | uint64_t id() const { | |||
_assert_(true); | _assert_(true); | |||
return id_; | return id_; | |||
} | } | |||
/** | /** | |||
* Get the ID number of the worker thread. | * Get the ID number of the worker thread. | |||
* @return the ID number of the worker thread. It is from 0 to less th an the number of | * @return the ID number of the worker thread. It is from 0 to less th an the number of | |||
* worker threads. | * worker threads. | |||
*/ | */ | |||
uint32_t thread_id() { | uint32_t thread_id() const { | |||
_assert_(true); | _assert_(true); | |||
return thid_; | return thid_; | |||
} | } | |||
/** | /** | |||
* Check whether the thread is to be aborted. | * Check whether the thread is to be aborted. | |||
* @return true if the thread is to be aborted, or false if not. | * @return true if the thread is to be aborted, or false if not. | |||
*/ | */ | |||
bool aborted() { | bool aborted() const { | |||
_assert_(true); | _assert_(true); | |||
return aborted_; | return aborted_; | |||
} | } | |||
private: | private: | |||
/** The task ID number. */ | /** The task ID number. */ | |||
uint64_t id_; | uint64_t id_; | |||
/** The thread ID number. */ | /** The thread ID number. */ | |||
uint64_t thid_; | uint64_t thid_; | |||
/** The flag to be aborted. */ | /** The flag to be aborted. */ | |||
bool aborted_; | bool aborted_; | |||
skipping to change at line 1115 | skipping to change at line 1115 | |||
*/ | */ | |||
virtual ~TaskQueue() { | virtual ~TaskQueue() { | |||
_assert_(true); | _assert_(true); | |||
} | } | |||
/** | /** | |||
* Process a task. | * Process a task. | |||
* @param task a task object. | * @param task a task object. | |||
*/ | */ | |||
virtual void do_task(Task* task) = 0; | virtual void do_task(Task* task) = 0; | |||
/** | /** | |||
* Process the starting event. | ||||
* @param task a task object. | ||||
* @note This is called for each thread on starting. | ||||
*/ | ||||
virtual void do_start(const Task* task) { | ||||
_assert_(true); | ||||
} | ||||
/** | ||||
* Process the finishing event. | ||||
* @param task a task object. | ||||
* @note This is called for each thread on finishing. | ||||
*/ | ||||
virtual void do_finish(const Task* task) { | ||||
_assert_(true); | ||||
} | ||||
/** | ||||
* Start the task queue. | * Start the task queue. | |||
* @param thnum the number of worker threads. | * @param thnum the number of worker threads. | |||
*/ | */ | |||
void start(size_t thnum) { | void start(size_t thnum) { | |||
_assert_(thnum > 0 && thnum <= MEMMAXSIZ); | _assert_(thnum > 0 && thnum <= MEMMAXSIZ); | |||
thary_ = new WorkerThread[thnum]; | thary_ = new WorkerThread[thnum]; | |||
for (size_t i = 0; i < thnum; i++) { | for (size_t i = 0; i < thnum; i++) { | |||
thary_[i].id_ = i; | thary_[i].id_ = i; | |||
thary_[i].queue_ = this; | thary_[i].queue_ = this; | |||
thary_[i].start(); | thary_[i].start(); | |||
skipping to change at line 1205 | skipping to change at line 1221 | |||
*/ | */ | |||
class WorkerThread : public Thread { | class WorkerThread : public Thread { | |||
friend class TaskQueue; | friend class TaskQueue; | |||
public: | public: | |||
explicit WorkerThread() : id_(0), queue_(NULL), aborted_(false) { | explicit WorkerThread() : id_(0), queue_(NULL), aborted_(false) { | |||
_assert_(true); | _assert_(true); | |||
} | } | |||
private: | private: | |||
void run() { | void run() { | |||
_assert_(true); | _assert_(true); | |||
Task* stask = new Task; | ||||
stask->thid_ = id_; | ||||
queue_->do_start(stask); | ||||
delete stask; | ||||
bool empty = false; | bool empty = false; | |||
while (true) { | while (true) { | |||
queue_->mutex_.lock(); | queue_->mutex_.lock(); | |||
if (aborted_) { | if (aborted_) { | |||
queue_->mutex_.unlock(); | queue_->mutex_.unlock(); | |||
break; | break; | |||
} | } | |||
if (empty) queue_->cond_.wait(&queue_->mutex_, 1.0); | if (empty) queue_->cond_.wait(&queue_->mutex_, 1.0); | |||
Task * task = NULL; | Task * task = NULL; | |||
if (queue_->tasks_.empty()) { | if (queue_->tasks_.empty()) { | |||
skipping to change at line 1226 | skipping to change at line 1246 | |||
} else { | } else { | |||
task = queue_->tasks_.front(); | task = queue_->tasks_.front(); | |||
task->thid_ = id_; | task->thid_ = id_; | |||
queue_->tasks_.pop_front(); | queue_->tasks_.pop_front(); | |||
queue_->count_--; | queue_->count_--; | |||
empty = false; | empty = false; | |||
} | } | |||
queue_->mutex_.unlock(); | queue_->mutex_.unlock(); | |||
if (task) queue_->do_task(task); | if (task) queue_->do_task(task); | |||
} | } | |||
Task* ftask = new Task; | ||||
ftask->thid_ = id_; | ||||
ftask->aborted_ = true; | ||||
queue_->do_finish(ftask); | ||||
delete ftask; | ||||
} | } | |||
uint32_t id_; | uint32_t id_; | |||
TaskQueue* queue_; | TaskQueue* queue_; | |||
Task* task_; | Task* task_; | |||
bool aborted_; | bool aborted_; | |||
}; | }; | |||
/** Dummy constructor to forbid the use. */ | /** Dummy constructor to forbid the use. */ | |||
TaskQueue(const TaskQueue&); | TaskQueue(const TaskQueue&); | |||
/** Dummy Operator to forbid the use. */ | /** Dummy Operator to forbid the use. */ | |||
TaskQueue& operator =(const TaskQueue&); | TaskQueue& operator =(const TaskQueue&); | |||
End of changes. 6 change blocks. | ||||
3 lines changed or deleted | 28 lines changed or added | |||