Refactored formula's use of boost::intrusive_ptr

This removes all the custom reference counting code from the
formula variant class, and also removes the WFL refcount() function.
The reference counting base class is also removed, since it is no longer used.
This commit is contained in:
Charles Dang 2016-07-25 01:47:00 +11:00 committed by Celtic Minstrel
parent 563947e1b3
commit 7a8f3ff110
18 changed files with 103 additions and 281 deletions

View file

@ -873,7 +873,6 @@
<Unit filename="../../src/random_new_synced.hpp" />
<Unit filename="../../src/recall_list_manager.cpp" />
<Unit filename="../../src/recall_list_manager.hpp" />
<Unit filename="../../src/reference_counted_object.hpp" />
<Unit filename="../../src/replay.cpp" />
<Unit filename="../../src/replay.hpp" />
<Unit filename="../../src/replay_controller.cpp" />

View file

@ -1982,7 +1982,6 @@
B55999B90EC62181008DD061 /* replay_controller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = replay_controller.cpp; sourceTree = "<group>"; };
B55999BA0EC62181008DD061 /* replay.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = replay.hpp; sourceTree = "<group>"; };
B55999BB0EC62181008DD061 /* replay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = replay.cpp; sourceTree = "<group>"; };
B55999BC0EC62181008DD061 /* reference_counted_object.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = reference_counted_object.hpp; sourceTree = "<group>"; };
B55999BF0EC62181008DD061 /* race.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = race.hpp; sourceTree = "<group>"; };
B55999C00EC62181008DD061 /* race.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = race.cpp; sourceTree = "<group>"; };
B55999C10EC62181008DD061 /* preferences_display.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = preferences_display.hpp; sourceTree = "<group>"; };
@ -3014,7 +3013,6 @@
EC84245A18F30D9000FC1EEF /* random_new_synced.hpp */,
EC1CB20619524AD600B0FA78 /* recall_list_manager.cpp */,
EC1CB20719524AD600B0FA78 /* recall_list_manager.hpp */,
B55999BC0EC62181008DD061 /* reference_counted_object.hpp */,
B55999BB0EC62181008DD061 /* replay.cpp */,
B55999BA0EC62181008DD061 /* replay.hpp */,
B55999B90EC62181008DD061 /* replay_controller.cpp */,

View file

@ -54,7 +54,6 @@
#include "undo_update_shroud_action.hpp"
#include <algorithm> // for reverse
#include <boost/intrusive_ptr.hpp> // for intrusive_ptr
#include <cassert> // for assert
#include <ostream> // for operator<<, basic_ostream, etc
#include <set> // for set

View file

@ -58,7 +58,6 @@
#include "formula/variant.hpp" // for variant
#include <algorithm> // for find, count, max, fill_n
#include <boost/smart_ptr/intrusive_ptr.hpp> // for intrusive_ptr
#include <cmath> // for sqrt
#include <cstdlib> // for abs
#include <ctime> // for time

View file

@ -54,7 +54,6 @@
#include "ai/game_info.hpp" // for move_result_ptr, move_map, etc
#include "candidates.hpp" // for base_candidate_action, etc
#include <boost/intrusive_ptr.hpp> // for intrusive_ptr
#include <cassert> // for assert
#include <ctime> // for time
#include <map> // for multimap<>::const_iterator, etc
@ -112,7 +111,6 @@ formula_ai::formula_ai(readonly_context &context, const config &cfg)
vars_(),
function_table_(*this)
{
add_ref();
init_readonly_context_proxy(context);
LOG_AI << "creating new formula ai"<< std::endl;
}
@ -167,7 +165,6 @@ std::string formula_ai::evaluate(const std::string& formula_str)
game_logic::formula f(formula_str, &function_table_);
game_logic::map_formula_callable callable(this);
callable.add_ref();
//formula_debugger fdb;
const variant v = f.evaluate(callable,nullptr);
@ -531,7 +528,6 @@ variant formula_ai::execute_variant(const variant& var, ai_context &ai_, bool co
*/
game_logic::map_formula_callable callable(this);
callable.add_ref();
if(error != variant())
callable.add("error", error);
@ -934,7 +930,6 @@ bool formula_ai::can_reach_unit(map_location unit_A, map_location unit_B) const
void formula_ai::on_create(){
//make sure we don't run out of refcount
vars_.add_ref();
for(const config &func : cfg_.child_range("function"))
{
@ -978,7 +973,6 @@ void formula_ai::evaluate_candidate_action(ca_ptr fai_ca)
bool formula_ai::execute_candidate_action(ca_ptr fai_ca)
{
game_logic::map_formula_callable callable(this);
callable.add_ref();
fai_ca->update_callable_map( callable );
const_formula_ptr move_formula(fai_ca->get_action());
return !make_action(move_formula, callable).is_empty();

View file

@ -77,7 +77,6 @@ candidate_action_with_filters::candidate_action_with_filters(
variant candidate_action_with_filters::do_filtering(ai::formula_ai* ai, variant& input, game_logic::const_formula_ptr formula)
{
game_logic::map_formula_callable callable(static_cast<const formula_callable*>(ai));
callable.add_ref();
callable.add("input", input);
return formula::evaluate(formula, callable);
@ -123,7 +122,6 @@ void move_candidate_action::evaluate(ai::formula_ai* ai, unit_map& units)
for(variant_iterator i = filtered_units.begin() ; i != filtered_units.end() ; ++i)
{
game_logic::map_formula_callable callable(static_cast<const formula_callable*>(ai));
callable.add_ref();
callable.add("me", *i);
int res = execute_formula(eval_, callable, ai);
@ -227,7 +225,6 @@ void attack_candidate_action::evaluate(ai::formula_ai* ai, unit_map& units)
if( ai->can_reach_unit( my_unit_callalbe->get_location(), enemy_units_flt[enemy_unit]->get_location() )) {
game_logic::map_formula_callable callable(static_cast<const formula_callable*>(ai));
callable.add_ref();
callable.add("me", filtered_my_units[my_unit]);
callable.add("target", filtered_enemy_units[enemy_unit]);

View file

@ -46,7 +46,6 @@ stage_side_formulas::~stage_side_formulas()
bool stage_side_formulas::do_play_stage()
{
game_logic::map_formula_callable callable(&fai_);
callable.add_ref();
try {
if (move_formula_) {
while( !fai_.make_action(move_formula_,callable).is_empty() ) { }

View file

@ -66,7 +66,6 @@ bool stage_unit_formulas::do_play_stage()
game_logic::const_formula_ptr priority_formula(fai_.create_optional_formula(i->formula_manager().get_priority_formula()));
if (priority_formula) {
game_logic::map_formula_callable callable(&fai_);
callable.add_ref();
callable.add("me", variant(new unit_callable(*i)));
priority = (game_logic::formula::evaluate(priority_formula, callable)).as_int();
} else {
@ -100,7 +99,6 @@ bool stage_unit_formulas::do_play_stage()
game_logic::const_formula_ptr formula(fai_.create_optional_formula(i->formula_manager().get_formula()));
if (formula) {
game_logic::map_formula_callable callable(&fai_);
callable.add_ref();
callable.add("me", variant(new unit_callable(*i)));
fai_.make_action(formula, callable);
} else {
@ -123,7 +121,6 @@ bool stage_unit_formulas::do_play_stage()
game_logic::const_formula_ptr loop_formula(fai_.create_optional_formula(i->formula_manager().get_loop_formula()));
if (loop_formula) {
game_logic::map_formula_callable callable(&fai_);
callable.add_ref();
callable.add("me", variant(new unit_callable(*i)));
while ( !fai_.make_action(loop_formula, callable).is_empty() && i.valid() )
{

View file

@ -15,7 +15,6 @@
#ifndef FORMULA_CALLABLE_HPP_INCLUDED
#define FORMULA_CALLABLE_HPP_INCLUDED
#include "reference_counted_object.hpp"
#include "formula/variant.hpp"
#include <memory>
@ -33,7 +32,7 @@ struct formula_input {
};
//interface for objects that can have formulae run on them
class formula_callable : public reference_counted_object {
class formula_callable {
public:
explicit formula_callable(bool has_self=true) : type_(FORMULA_C), has_self_(has_self)
{}
@ -104,14 +103,6 @@ private:
bool has_self_;
};
class formula_callable_no_ref_count : public formula_callable {
public:
formula_callable_no_ref_count() {
turn_reference_counting_off();
}
virtual ~formula_callable_no_ref_count() {}
};
class formula_callable_with_backup : public formula_callable {
const formula_callable& main_;
const formula_callable& backup_;
@ -175,8 +166,8 @@ private:
const formula_callable* fallback_;
};
typedef boost::intrusive_ptr<map_formula_callable> map_formula_callable_ptr;
typedef boost::intrusive_ptr<const map_formula_callable> const_map_formula_callable_ptr;
typedef std::shared_ptr<map_formula_callable> map_formula_callable_ptr;
typedef std::shared_ptr<const map_formula_callable> const_map_formula_callable_ptr;
}

View file

@ -15,14 +15,12 @@
#ifndef FORMULA_CALLABLE_FWD_HPP_INCLUDED
#define FORMULA_CALLABLE_FWD_HPP_INCLUDED
#include <boost/intrusive_ptr.hpp>
namespace game_logic {
class formula_callable;
class formula_debugger;
typedef boost::intrusive_ptr<formula_callable> formula_callable_ptr;
typedef boost::intrusive_ptr<const formula_callable> const_formula_callable_ptr;
typedef std::shared_ptr<formula_callable> formula_callable_ptr;
typedef std::shared_ptr<const formula_callable> const_formula_callable_ptr;
}

View file

@ -11,6 +11,7 @@
*/
#include "global.hpp"
#include <cassert>
#include <iostream>
#include <set>
#include <sstream>

View file

@ -98,7 +98,6 @@ private:
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
variant var = args()[0]->evaluate(variables, fdb);
const formula_callable* callable = var.as_callable();
callable->add_ref();
std::vector<formula_input> inputs = callable->inputs();
std::vector<variant> res;
for(size_t i=0; i<inputs.size(); ++i) {
@ -767,7 +766,6 @@ private:
}
} else {
map_formula_callable self_callable;
self_callable.add_ref();
const std::string self = args()[1]->evaluate(variables,fdb).as_string();
for(variant_iterator it = items.begin(); it != items.end(); ++it) {
self_callable.add(self, *it);
@ -937,7 +935,6 @@ private:
}
} else {
map_formula_callable self_callable;
self_callable.add_ref();
const std::string self = args()[1]->evaluate(variables,fdb).as_string();
for(variant_iterator it = items.begin(); it != items.end(); ++it) {
self_callable.add(self, *it);
@ -975,7 +972,6 @@ private:
}
} else {
map_formula_callable self_callable;
self_callable.add_ref();
const std::string self = args()[1]->evaluate(variables,fdb).as_string();
for(variant_iterator it = items.begin(); it != items.end(); ++it){
self_callable.add(self, *it);
@ -1011,7 +1007,6 @@ private:
}
} else {
map_formula_callable self_callable;
self_callable.add_ref();
const std::string self = args()[1]->evaluate(variables,fdb).as_string();
for(variant_iterator it = items.begin(); it != items.end(); ++it) {
self_callable.add(self, *it);
@ -1117,7 +1112,6 @@ private:
++it;
}
map_formula_callable self_callable;
self_callable.add_ref();
for(; it != items.end(); ++it) {
self_callable.add("a", res);
self_callable.add("b", *it);
@ -1383,18 +1377,6 @@ private:
}
};
class refcount_function : public function_expression {
public:
explicit refcount_function(const args_list& args)
: function_expression("refcount", args, 1, 1)
{}
private:
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
return variant(args()[0]->evaluate(variables,fdb).refcount());
}
};
class loc_function : public function_expression {
public:
explicit loc_function(const args_list& args)
@ -1594,7 +1576,6 @@ function_symbol_table& get_functions_map() {
FUNCTION(sgn);
FUNCTION(round);
FUNCTION(as_decimal);
FUNCTION(refcount);
FUNCTION(pair);
FUNCTION(loc);
FUNCTION(distance_between);

View file

@ -14,6 +14,7 @@
#include "global.hpp"
#include <cassert>
#include <cmath>
#include <iostream>
#include <string.h>
@ -247,86 +248,20 @@ bool variant_iterator::operator!=(const variant_iterator& that) const
return true;
}
struct variant_list {
variant_list()
: elements()
, refcount(0)
{
}
std::vector<variant> elements;
int refcount;
};
struct variant_string {
variant_string()
: str()
, refcount(0)
{
}
std::string str;
int refcount;
};
struct variant_map {
variant_map()
: elements()
, refcount(0)
{
}
std::map<variant,variant> elements;
int refcount;
};
void variant::increment_refcount()
{
switch(type_) {
case TYPE_LIST:
++list_->refcount;
break;
case TYPE_STRING:
++string_->refcount;
break;
case TYPE_MAP:
++map_->refcount;
break;
case TYPE_CALLABLE:
intrusive_ptr_add_ref(callable_);
break;
// These are not used here, add them to silence a compiler warning.
case TYPE_NULL:
case TYPE_DECIMAL:
case TYPE_INT :
break;
}
}
void variant::release()
{
switch(type_) {
case TYPE_LIST:
if(--list_->refcount == 0) {
delete list_;
}
delete list_;
break;
case TYPE_STRING:
if(--string_->refcount == 0) {
delete string_;
}
delete string_;
break;
case TYPE_MAP:
if(--map_->refcount == 0) {
delete map_;
}
delete map_;
break;
case TYPE_CALLABLE:
intrusive_ptr_release(callable_);
break;
// These are not used here, add them to silence a compiler warning.
case TYPE_CALLABLE:
case TYPE_NULL:
case TYPE_DECIMAL:
case TYPE_INT :
@ -350,9 +285,9 @@ variant::variant(int n, variant::DECIMAL_VARIANT_TYPE /*type*/) : type_(TYPE_DEC
variant::variant(double n, variant::DECIMAL_VARIANT_TYPE /*type*/) : type_(TYPE_DECIMAL) {
n *= 1000;
decimal_value_ = static_cast<int>(n);
n -= decimal_value_;
if(n > 0.5)
decimal_value_++;
else if(n < -0.5)
@ -363,40 +298,53 @@ variant::variant(const game_logic::formula_callable* callable)
: type_(TYPE_CALLABLE), callable_(callable)
{
assert(callable_);
increment_refcount();
}
variant::variant(std::vector<variant>* array)
: type_(TYPE_LIST)
{
assert(array);
list_ = new variant_list;
list_->elements.swap(*array);
increment_refcount();
list_ = new std::vector<variant>(*array);
}
variant::variant(const std::string& str)
: type_(TYPE_STRING)
{
string_ = new variant_string;
string_->str = str;
increment_refcount();
string_ = new std::string(str);
}
variant::variant(std::map<variant,variant>* map)
: type_(TYPE_MAP)
{
assert(map);
map_ = new variant_map;
map_->elements.swap(*map);
increment_refcount();
map_ = new std::map<variant,variant>(*map);
}
variant::variant(const variant& v)
: type_(v.type_)
{
memcpy(this, &v, sizeof(v));
increment_refcount();
switch(type_) {
case TYPE_INT:
int_value_ = v.int_value_;
break;
case TYPE_DECIMAL:
decimal_value_ = v.decimal_value_;
break;
case TYPE_LIST:
list_ = new std::vector<variant>(*v.list_);
break;
case TYPE_STRING:
string_ = new std::string(*v.string_);
break;
case TYPE_MAP:
map_ = new std::map<variant,variant>(*v.map_);
break;
case TYPE_CALLABLE:
callable_ = v.callable_;
break;
case TYPE_NULL:
break;
}
}
variant::~variant()
@ -407,9 +355,8 @@ variant::~variant()
variant& variant::operator=(const variant& v)
{
if(&v != this) {
release();
memcpy(this, &v, sizeof(v));
increment_refcount();
this->~variant();
new(this) variant(v);
}
return *this;
}
@ -422,11 +369,11 @@ variant variant::operator[](size_t n) const
must_be(TYPE_LIST);
assert(list_);
if(n >= list_->elements.size()) {
if(n >= list_->size()) {
throw type_error("invalid index");
}
return list_->elements[n];
return (*list_)[n];
}
variant variant::operator[](const variant& v) const
@ -437,8 +384,8 @@ variant variant::operator[](const variant& v) const
if(type_ == TYPE_MAP) {
assert(map_);
std::map<variant,variant>::const_iterator i = map_->elements.find(v);
if (i == map_->elements.end())
std::map<variant,variant>::const_iterator i = map_->find(v);
if (i == map_->end())
{
static variant null_variant;
return null_variant;
@ -447,7 +394,7 @@ variant variant::operator[](const variant& v) const
} else if(type_ == TYPE_LIST) {
if(v.is_list()) {
std::vector<variant> slice;
for(size_t i = 0; i < v.num_elements(); ++i) {
slice.push_back( (*this)[v[i]] );
}
@ -468,7 +415,7 @@ variant variant::get_keys() const
must_be(TYPE_MAP);
assert(map_);
std::vector<variant> tmp;
for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
for(std::map<variant,variant>::const_iterator i=map_->begin(); i != map_->end(); ++i) {
tmp.push_back(i->first);
}
return variant(&tmp);
@ -479,7 +426,7 @@ variant variant::get_values() const
must_be(TYPE_MAP);
assert(map_);
std::vector<variant> tmp;
for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
for(std::map<variant,variant>::const_iterator i=map_->begin(); i != map_->end(); ++i) {
tmp.push_back(i->second);
}
return variant(&tmp);
@ -488,20 +435,20 @@ variant variant::get_values() const
variant_iterator variant::begin() const
{
if(type_ == TYPE_LIST)
return variant_iterator( list_->elements.begin() );
return variant_iterator( list_->begin() );
if(type_ == TYPE_MAP)
return variant_iterator( map_->elements.begin() );
return variant_iterator( map_->begin() );
return variant_iterator();
}
variant_iterator variant::end() const
{
if(type_ == TYPE_LIST)
return variant_iterator( list_->elements.end() );
return variant_iterator( list_->end() );
if(type_ == TYPE_MAP)
return variant_iterator( map_->elements.end() );
return variant_iterator( map_->end() );
return variant_iterator();
}
@ -512,10 +459,10 @@ bool variant::is_empty() const
return true;
} else if (type_ == TYPE_LIST) {
assert(list_);
return list_->elements.empty();
return list_->empty();
} else if (type_ == TYPE_MAP) {
assert(map_);
return map_->elements.empty();
return map_->empty();
}
return false;
@ -529,10 +476,10 @@ size_t variant::num_elements() const
if (type_ == TYPE_LIST) {
assert(list_);
return list_->elements.size();
return list_->size();
} else if (type_ == TYPE_MAP) {
assert(map_);
return map_->elements.size();
return map_->size();
} else {
throw type_error((formatter() << "type error: "
<< " expected a list or a map but found " << type_string()
@ -587,11 +534,11 @@ bool variant::as_bool() const
case TYPE_CALLABLE:
return callable_ != nullptr;
case TYPE_LIST:
return !list_->elements.empty();
return !list_->empty();
case TYPE_MAP:
return !map_->elements.empty();
return !map_->empty();
case TYPE_STRING:
return !string_->str.empty();
return !string_->empty();
default:
assert(false);
return false;
@ -602,21 +549,21 @@ const std::string& variant::as_string() const
{
must_be(TYPE_STRING);
assert(string_);
return string_->str;
return *string_;
}
const std::vector<variant>& variant::as_list() const
{
must_be(TYPE_LIST);
assert(list_);
return list_->elements;
return *list_;
}
const std::map<variant,variant>& variant::as_map() const
{
must_be(TYPE_MAP);
assert(map_);
return map_->elements;
return *map_;
}
variant variant::operator+(const variant& v) const
@ -624,14 +571,14 @@ variant variant::operator+(const variant& v) const
if(type_ == TYPE_LIST) {
if(v.type_ == TYPE_LIST) {
std::vector<variant> res;
res.reserve(list_->elements.size() + v.list_->elements.size());
for(size_t i = 0; i<list_->elements.size(); ++i) {
const variant& var = list_->elements[i];
res.reserve(list_->size() + v.list_->size());
for(size_t i = 0; i<list_->size(); ++i) {
const variant& var = (*list_)[i];
res.push_back(var);
}
for(size_t j = 0; j<v.list_->elements.size(); ++j) {
const variant& var = v.list_->elements[j];
for(size_t j = 0; j<v.list_->size(); ++j) {
const variant& var = (*v.list_)[j];
res.push_back(var);
}
@ -640,9 +587,9 @@ variant variant::operator+(const variant& v) const
}
if(type_ == TYPE_MAP) {
if(v.type_ == TYPE_MAP) {
std::map<variant,variant> res(map_->elements);
std::map<variant,variant> res(*map_);
for(std::map<variant,variant>::const_iterator i = v.map_->elements.begin(); i != v.map_->elements.end(); ++i) {
for(std::map<variant,variant>::const_iterator i = v.map_->begin(); i != v.map_->end(); ++i) {
res[i->first] = i->second;
}
@ -729,7 +676,7 @@ variant variant::operator%(const variant& v) const
if(denominator == 0) {
throw type_error((formatter() << "divide by zero error").str());
}
return variant(numerator%denominator, DECIMAL_VARIANT);
} else {
const int numerator = as_int();
@ -748,7 +695,7 @@ variant variant::operator^(const variant& v) const
if( type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL ) {
double res = pow( as_decimal()/1000.0 , v.as_decimal()/1000.0 );
if(res != res) return variant();
return variant(res, DECIMAL_VARIANT);
@ -782,7 +729,7 @@ bool variant::operator==(const variant& v) const
}
case TYPE_STRING: {
return string_->str == v.string_->str;
return *string_ == *v.string_;
}
case TYPE_INT: {
@ -808,7 +755,7 @@ bool variant::operator==(const variant& v) const
}
case TYPE_MAP: {
return map_->elements == v.map_->elements;
return *map_ == *v.map_;
}
case TYPE_CALLABLE: {
@ -843,7 +790,7 @@ bool variant::operator<=(const variant& v) const
}
case TYPE_STRING: {
return string_->str <= v.string_->str;
return *string_ <= *v.string_;
}
case TYPE_INT: {
@ -867,7 +814,7 @@ bool variant::operator<=(const variant& v) const
}
case TYPE_MAP: {
return map_->elements <= v.map_->elements;
return *map_ <= *v.map_;
}
case TYPE_CALLABLE: {
@ -970,18 +917,18 @@ variant variant::concatenate(const variant& v) const
{
if(type_ == TYPE_LIST) {
v.must_be(TYPE_LIST);
std::vector< variant > res;
res.reserve(num_elements() + v.num_elements());
for(size_t i = 0; i < num_elements(); ++i) {
res.push_back( (*this)[i] );
}
for(size_t i = 0; i < v.num_elements(); ++i) {
res.push_back( v[i] );
}
return variant( &res );
} else if(type_ == TYPE_STRING) {
v.must_be(TYPE_STRING);
@ -999,17 +946,17 @@ variant variant::concatenate(const variant& v) const
variant variant::build_range(const variant& v) const {
must_be(TYPE_INT);
v.must_be(TYPE_INT);
int lhs = as_int(), rhs = v.as_int();
int len = abs(rhs - lhs) + 1;
std::vector< variant > res;
res.reserve(len);
for(size_t i = lhs; res.size() != res.capacity(); lhs < rhs ? ++i : --i) {
res.push_back( variant(i) );
}
return variant( &res );
}
@ -1021,13 +968,13 @@ bool variant::contains(const variant& v) const {
<< variant_type_to_string(type_)
<< " (" << to_debug_string() << ")").str());
}
if(type_ == TYPE_LIST) {
variant_iterator iter = std::find(begin(), end(), v);
return iter != end();
} else {
std::map<variant,variant>::const_iterator iter = map_->elements.find(v);
return iter != map_->elements.end();
std::map<variant,variant>::const_iterator iter = map_->find(v);
return iter != map_->end();
}
}
@ -1077,8 +1024,8 @@ void variant::serialize_to_string(std::string& str) const
case TYPE_LIST: {
str += "[";
bool first_time = true;
for(size_t i=0; i<list_->elements.size(); ++i) {
const variant& var = list_->elements[i];
for(size_t i=0; i<list_->size(); ++i) {
const variant& var = (*list_)[i];
if(!first_time) {
str += ",";
}
@ -1091,7 +1038,7 @@ void variant::serialize_to_string(std::string& str) const
case TYPE_MAP: {
str += "[";
bool first_time = true;
for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
for(std::map<variant,variant>::const_iterator i=map_->begin(); i != map_->end(); ++i) {
if(!first_time) {
str += ",";
}
@ -1100,7 +1047,7 @@ void variant::serialize_to_string(std::string& str) const
str += "->";
i->second.serialize_to_string(str);
}
if(map_->elements.empty()) {
if(map_->empty()) {
str += "->";
}
str += "]";
@ -1108,7 +1055,7 @@ void variant::serialize_to_string(std::string& str) const
}
case TYPE_STRING:
str += "'";
for(std::string::iterator it = string_->str.begin(); it < string_->str.end(); ++it) {
for(std::string::iterator it = string_->begin(); it < string_->end(); ++it) {
switch(*it) {
case '\'':
str += "[']";
@ -1140,26 +1087,6 @@ void variant::serialize_from_string(const std::string& str)
}
}
int variant::refcount() const
{
switch(type_) {
case TYPE_LIST:
return list_->refcount;
break;
case TYPE_STRING:
return string_->refcount;
break;
case TYPE_MAP:
return map_->refcount;
break;
case TYPE_CALLABLE:
return callable_->refcount();
break;
default:
return -1;
}
}
std::string variant::string_cast() const
{
switch(type_) {
@ -1192,8 +1119,8 @@ std::string variant::string_cast() const
return "(object)";
case TYPE_LIST: {
std::string res = "";
for(size_t i=0; i<list_->elements.size(); ++i) {
const variant& var = list_->elements[i];
for(size_t i=0; i<list_->size(); ++i) {
const variant& var = (*list_)[i];
if(!res.empty()) {
res += ", ";
}
@ -1205,7 +1132,7 @@ std::string variant::string_cast() const
}
case TYPE_MAP: {
std::string res = "";
for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
for(std::map<variant,variant>::const_iterator i=map_->begin(); i != map_->end(); ++i) {
if(!res.empty()) {
res += ",";
}
@ -1217,7 +1144,7 @@ std::string variant::string_cast() const
}
case TYPE_STRING:
return string_->str;
return *string_;
default:
assert(false);
return "invalid";
@ -1304,7 +1231,7 @@ std::string variant::to_debug_string(std::vector<const game_logic::formula_calla
case TYPE_MAP: {
s << "[";
bool first_time = true;
for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
for(std::map<variant,variant>::const_iterator i=map_->begin(); i != map_->end(); ++i) {
if(!first_time) {
s << ",";
}
@ -1317,7 +1244,7 @@ std::string variant::to_debug_string(std::vector<const game_logic::formula_calla
break;
}
case TYPE_STRING: {
s << "'" << string_->str << "'";
s << "'" << *string_ << "'";
break;
}
}

View file

@ -38,9 +38,6 @@ struct call_stack_manager {
}
};
struct variant_list;
struct variant_string;
struct variant_map;
class variant_iterator;
struct type_error : public game::error {
@ -153,8 +150,6 @@ public:
void serialize_to_string(std::string& str) const;
void serialize_from_string(const std::string& str);
int refcount() const;
std::string string_cast() const;
std::string to_debug_string(std::vector<const game_logic::formula_callable*>* seen=nullptr, bool verbose = false) const;
@ -167,12 +162,11 @@ private:
int decimal_value_;
const game_logic::formula_callable* callable_;
game_logic::formula_callable* mutable_callable_;
variant_list* list_;
variant_string* string_;
variant_map* map_;
std::vector<variant>* list_;
std::string* string_;
std::map<variant,variant>* map_;
};
void increment_refcount();
void release();
};

View file

@ -1,52 +0,0 @@
/*
Copyright (C) 2008 - 2016 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef REFERENCE_COUNTED_OBJECT_HPP_INCLUDED
#define REFERENCE_COUNTED_OBJECT_HPP_INCLUDED
#include <boost/intrusive_ptr.hpp>
class reference_counted_object
{
public:
reference_counted_object() : count_(0) {}
reference_counted_object(const reference_counted_object& /*obj*/) : count_(0) {}
reference_counted_object& operator=(const reference_counted_object& /*obj*/) {
return *this;
}
virtual ~reference_counted_object() {}
void add_ref() const { ++count_; }
void dec_ref() const { if(--count_ == 0) { delete const_cast<reference_counted_object*>(this); } }
int refcount() const { return count_; }
protected:
void turn_reference_counting_off() const { count_ = 1000000; }
private:
mutable int count_;
};
inline void intrusive_ptr_add_ref(const reference_counted_object* obj) {
obj->add_ref();
}
inline void intrusive_ptr_release(const reference_counted_object* obj) {
obj->dec_ref();
}
typedef boost::intrusive_ptr<reference_counted_object> object_ptr;
typedef boost::intrusive_ptr<const reference_counted_object> const_object_ptr;
#endif

View file

@ -567,7 +567,7 @@ bool basic_unit_filter_impl::internal_matches_filter(const unit & u, const map_l
const unit_callable main(loc,u);
game_logic::map_formula_callable callable(&main);
if (u2) {
boost::intrusive_ptr<unit_callable> secondary(new unit_callable(*u2));
std::shared_ptr<unit_callable> secondary(new unit_callable(*u2));
callable.add("other", variant(secondary.get()));
// It's not destroyed upon scope exit because the variant holds a reference
}

View file

@ -23,7 +23,7 @@
void unit_formula_manager::add_formula_var(std::string str, variant var)
{
if(!formula_vars_) formula_vars_ = new game_logic::map_formula_callable;
if(!formula_vars_) formula_vars_ = std::make_shared<game_logic::map_formula_callable>();
formula_vars_->add(str, var);
}
@ -35,7 +35,7 @@ void unit_formula_manager::read(const config & ai)
if (const config &ai_vars = ai.child("vars"))
{
formula_vars_ = new game_logic::map_formula_callable;
formula_vars_ = std::make_shared<game_logic::map_formula_callable>();
variant var;
for (const config::attribute &i : ai_vars.attribute_range()) {

View file

@ -31,7 +31,7 @@ public:
unit_formula_(o.unit_formula_),
unit_loop_formula_(o.unit_loop_formula_),
unit_priority_formula_(o.unit_priority_formula_),
formula_vars_(o.formula_vars_ ? new game_logic::map_formula_callable(*o.formula_vars_) : o.formula_vars_)
formula_vars_(o.formula_vars_ ? std::make_shared<game_logic::map_formula_callable>(*o.formula_vars_) : o.formula_vars_)
{}
const game_logic::map_formula_callable_ptr& formula_vars() const { return formula_vars_; }