Changed the value object to allocate its larger members.

This commit is contained in:
John Wiegley 2007-05-19 02:59:05 +00:00
parent 7ddf6baf2c
commit 565d8eeb87
2 changed files with 73 additions and 28 deletions

View file

@ -44,16 +44,16 @@ void value_t::storage_t::destroy()
((amount_t *)data)->~amount_t();
break;
case BALANCE:
((balance_t *)data)->~balance_t();
checked_delete(*(balance_t **)data);
break;
case BALANCE_PAIR:
((balance_pair_t *)data)->~balance_pair_t();
checked_delete(*(balance_pair_t **)data);
break;
case STRING:
((string *)data)->~string();
break;
case SEQUENCE:
((sequence_t *)data)->~sequence_t();
checked_delete(*(sequence_t **)data);
break;
case POINTER:
((boost::any *)data)->~any();
@ -67,6 +67,10 @@ void value_t::storage_t::destroy()
void value_t::initialize()
{
#if 0
LOGGER("value.initialize");
#endif
true_value = new storage_t;
true_value->type = BOOLEAN;
*(bool *) true_value->data = true;
@ -74,6 +78,38 @@ void value_t::initialize()
false_value = new storage_t;
false_value->type = BOOLEAN;
*(bool *) false_value->data = false;
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(bool));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(moment_t));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(long));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(amount_t));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(balance_t *));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(balance_pair_t *));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(string));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(sequence_t *));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(xml::node_t *));
BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(boost::any));
#if 0
DEBUG_(std::setw(3) << std::right << sizeof(bool)
<< " sizeof(bool)");
DEBUG_(std::setw(3) << std::right << sizeof(moment_t)
<< " sizeof(moment_t)");
DEBUG_(std::setw(3) << std::right << sizeof(long)
<< " sizeof(long)");
DEBUG_(std::setw(3) << std::right << sizeof(amount_t)
<< " sizeof(amount_t)");
DEBUG_(std::setw(3) << std::right << sizeof(balance_t *)
<< " sizeof(balance_t *)");
DEBUG_(std::setw(3) << std::right << sizeof(balance_pair_t *)
<< " sizeof(balance_pair_t *)");
DEBUG_(std::setw(3) << std::right << sizeof(string)
<< " sizeof(string)");
DEBUG_(std::setw(3) << std::right << sizeof(sequence_t *)
<< " sizeof(sequence_t *)");
DEBUG_(std::setw(3) << std::right << sizeof(boost::any)
<< " sizeof(boost::any)");
#endif
}
void value_t::shutdown()

View file

@ -82,25 +82,16 @@ public:
private:
class storage_t
{
char data[sizeof(balance_pair_t)];
char data[sizeof(amount_t)];
type_t type;
BOOST_STATIC_ASSERT(sizeof(balance_pair_t) > sizeof(bool));
BOOST_STATIC_ASSERT(sizeof(balance_pair_t) > sizeof(moment_t));
BOOST_STATIC_ASSERT(sizeof(balance_pair_t) > sizeof(long));
BOOST_STATIC_ASSERT(sizeof(balance_pair_t) > sizeof(amount_t));
BOOST_STATIC_ASSERT(sizeof(balance_pair_t) > sizeof(balance_t));
BOOST_STATIC_ASSERT(sizeof(balance_pair_t) > sizeof(string));
BOOST_STATIC_ASSERT(sizeof(balance_pair_t) > sizeof(sequence_t));
BOOST_STATIC_ASSERT(sizeof(balance_pair_t) > sizeof(xml::node_t *));
explicit storage_t() : type(VOID), refc(0) {
TRACE_CTOR(value_t::storage_t, "");
}
explicit storage_t(const storage_t& rhs)
: type(rhs.type), refc(0) {
TRACE_CTOR(value_t::storage_t, "");
std::memcpy(data, rhs.data, sizeof(balance_pair_t));
std::memcpy(data, rhs.data, sizeof(data));
}
public: // so `checked_delete' can access it
@ -114,7 +105,7 @@ private:
private:
storage_t& operator=(const storage_t& rhs) {
type = rhs.type;
std::memcpy(data, rhs.data, sizeof(balance_pair_t));
std::memcpy(data, rhs.data, sizeof(data));
return *this;
}
@ -244,8 +235,28 @@ public:
*/
void _dup() {
assert(storage);
if (storage->refc > 1)
if (storage->refc > 1) {
storage = new storage_t(*storage.get());
// If the data referenced by storage is an allocated pointer, we
// need to create a new object in order to achieve duplication.
switch (storage->type) {
case BALANCE:
*(balance_t **) storage->data =
new balance_t(**(balance_t **) storage->data);
break;
case BALANCE_PAIR:
*(balance_pair_t **) storage->data =
new balance_pair_t(**(balance_pair_t **) storage->data);
break;
case SEQUENCE:
*(sequence_t **) storage->data =
new sequence_t(**(sequence_t **) storage->data);
break;
default:
break; // everything else has been duplicated
}
}
}
void _clear() {
if (! storage || storage->refc > 1)
@ -254,10 +265,8 @@ public:
storage->destroy();
}
void _reset() {
if (storage) {
storage->destroy();
if (storage)
storage = intrusive_ptr<storage_t>();
}
}
operator bool() const;
@ -367,15 +376,15 @@ public:
balance_t& as_balance_lval() {
assert(is_balance());
_dup();
return *(balance_t *) storage->data;
return **(balance_t **) storage->data;
}
const balance_t& as_balance() const {
assert(is_balance());
return *(balance_t *) storage->data;
return **(balance_t **) storage->data;
}
void set_balance(const balance_t& val) {
set_type(BALANCE);
new((balance_t *) storage->data) balance_t(val);
*(balance_t **) storage->data = new balance_t(val);
}
bool is_balance_pair() const {
@ -384,15 +393,15 @@ public:
balance_pair_t& as_balance_pair_lval() {
assert(is_balance_pair());
_dup();
return *(balance_pair_t *) storage->data;
return **(balance_pair_t **) storage->data;
}
const balance_pair_t& as_balance_pair() const {
assert(is_balance_pair());
return *(balance_pair_t *) storage->data;
return **(balance_pair_t **) storage->data;
}
void set_balance_pair(const balance_pair_t& val) {
set_type(BALANCE_PAIR);
new((balance_pair_t *) storage->data) balance_pair_t(val);
*(balance_pair_t **) storage->data = new balance_pair_t(val);
}
bool is_string() const {
@ -418,15 +427,15 @@ public:
sequence_t& as_sequence_lval() {
assert(is_sequence());
_dup();
return *(sequence_t *) storage->data;
return **(sequence_t **) storage->data;
}
const sequence_t& as_sequence() const {
assert(is_sequence());
return *(sequence_t *) storage->data;
return **(sequence_t **) storage->data;
}
void set_sequence(const sequence_t& val) {
set_type(SEQUENCE);
new((sequence_t *) storage->data) sequence_t(val);
*(sequence_t **) storage->data = new sequence_t(val);
}
bool is_xml_node() const {