Commit 86c62dda authored by Adam Helps's avatar Adam Helps Committed by Martin Marinov

TSP-3429 TSP-3435 Handles and reference counts (#9)

* Adds optional pre-call and post-call events in the journal to implement reference count abridgement.
* Adds new documentation for many functions, and improves existing.
* Removes "JOURNAL_FUNCTION" from the created macros when journal is turned off, because there is no such macro when journal is turned on.
* Adds the ability to unlink names in the journal manually. This was already being done by destructors, but there wasn't a way to do it for names managed in other ways.
* Add HandleT<> to support handle tracking
* Generalize the key<> function to handles and make key a pair of size_t 
* Simplify ReturnLink and make it work for HandleT<>
* Adds an operator< to the HandleT class so that it can be used as a key in associative containers (T-Splines uses it this way for ref-count collapsing).
parent 5ee99aa8
......@@ -290,11 +290,17 @@ template <typename T> Data define(Stream& _strm, const CArrayT<T>& _c_arr)
return Data(name);
}
template <class T> Data define(Stream&, const ReturnLinkT<T>& _rtrn)
template <> inline Data define(Stream&, const ReturnLink& _rtrn)
{
return Data(String("auto ") + _rtrn.link.name);
}
template <typename PointerT, typename IndexT>
Data define(Stream& _strm, const HandleT<PointerT, IndexT>& _hndl)
{
return Data(_strm.retrieve_unique_name(key(_hndl)));
}
inline void define_append_argument(Stream&, String&, const bool) {}
template <typename NextT, typename... RestT>
......@@ -341,7 +347,12 @@ template <typename T> Data define_in_language(Stream& _strm, const T& _arg)
JOURNAL_TYPE_NAME(TYPE); \
template <> Data define(Stream&, TYPE const&) { return Data(); }
// an internal type that is tracked by the name book at all time
/*!
This generates the appropriate type_name and define functions for
an internal type that is tracked by the name book at all times. This
is appropriate for opaque pointers whose value always first
appears when it is returned from a journaled function.
*/
#define JOURNAL_ADD_TYPE_INTERNAL_TRACKED(TYPE, VRBL) \
JOURNAL_ADD_TYPE_INTERNAL(TYPE); \
template <> Data define(Stream& _strm, TYPE* const& VRBL) \
......
......@@ -18,7 +18,6 @@
namespace Journal
{
#define JOURNAL_WRAP(EXPR) \
try \
{ \
......@@ -82,6 +81,11 @@ void Stream::link_unique_name(const Key _key, const char* const _name)
JOURNAL_WRAP(impl_->link_unique_name(_key, _name));
}
void Stream::unlink_unique_name(const Key _key)
{
JOURNAL_WRAP(impl_->unlink_unique_name(_key));
}
const char* Stream::search_unique_name(const Key _key) const
{
JOURNAL_WRAP_RETURN(impl_->search_unique_name(_key));
......@@ -106,7 +110,8 @@ void Stream::emit_constructor(
void Stream::emit_destructor(const char* const _fnct, const Key& _obj)
{
JOURNAL_WRAP(impl_->emit_destructor_and_unlink(_fnct, _obj));
JOURNAL_WRAP(impl_->emit_destructor(_fnct, _obj));
unlink_unique_name(_obj);
}
void Stream::emit_method_outcome(
......
This diff is collapsed.
......@@ -26,10 +26,6 @@ Stream::Impl::Impl(const char* const _cmpn_name, const char* const _base_path)
{
if (!make_directory(jrnl_path_)) // failed to make the directory?
throw INIT_FAILED;
name_idx_ = 0;
name_book_.clear();
key_name_.clear();
}
Stream::Impl::~Impl() {}
......@@ -115,33 +111,42 @@ const char* Stream::Impl::book_unique_name(const char* const _name)
void Stream::Impl::link_unique_name(const Key _key, const char* const _name)
{
JOURNAL_ERROR_if(_key == INVALID_KEY, "INVALID_KEY for " << _name);
key_name_[_key] = _name;
// TODO: do we want to have the concept of an customizable invalid key for
// any key that is supported, i.e, 0 for pointers, SIZE_T_MAX for others, etc?
// If yes, we should expand such checks to the complete API
// JOURNAL_ERROR_if(_key == invld_key, "INVALID_KEY for " << _name);
key_name_map_[_key] = _name;
}
void Stream::Impl::unlink_unique_name(const Key _key)
{
key_name_map_.erase(_key);
}
const char* Stream::Impl::search_unique_name(const Key _key) const
{
const auto it = key_name_.find(_key);
return it == key_name_.end() ? nullptr : it->second;
const auto it = key_name_map_.find(_key);
return it == key_name_map_.end() ? nullptr : it->second;
}
const char* Stream::Impl::retrieve_unique_name(const Key _key)
const char* Stream::Impl::retrieve_unique_name(const Key _key) const
{
const auto* name = search_unique_name(_key);
JOURNAL_ERROR_if_do(name == nullptr,
"Unique name not stored for key "
<< Base::format_hex(_key, Base::FormatHex::PREFIX_0x),
"Unique name not stored for key <"
<< Base::format_hex(_key.first, Base::FormatHex::PREFIX_0x) << ", "
<< Base::format_hex(_key.second, Base::FormatHex::PREFIX_0x) << '>',
return "UNKNOWN_key");
return name;
}
bool Stream::Impl::obtain_unique_name(
const Key _key, const char* const _name_base, const char*& _name)
const Key _key, const char* const _name_base, const char*& _name)
{
_name = search_unique_name(_key);
if (_name != nullptr)
return false;
_name = book_unique_name(_name_base);
_name = stream().book_unique_name(_name_base);
link_unique_name(_key, _name);
return true;
}
......@@ -152,12 +157,6 @@ void Stream::Impl::time()
<< System::Environment::time(); // time() already contains ENDL
}
void Stream::Impl::emit_destructor_and_unlink(const char* const _fnct, const Key& _obj)
{
emit_destructor(_fnct, _obj);
key_name_.erase(_obj); // erase the link
}
}//namespace Journal
#endif//JOURNAL_ON
......@@ -13,8 +13,8 @@
#include <Base/Journal/JournalStream.hh>
#include <Base/Utils/OStringStream.hh>
#include <map>
#include <set>
#include <map>
#include <fstream>
namespace Journal
......@@ -46,8 +46,9 @@ public:
String make_unique_name(const char* const _name);
const char* book_unique_name(const char* const _name);
void link_unique_name(const Key _key, const char* const _name);
void unlink_unique_name(const Key _key);
const char* search_unique_name(const Key _key) const;
const char* retrieve_unique_name(const Key _key);
const char* retrieve_unique_name(const Key _key) const;
bool obtain_unique_name(
const Key _key, const char* const _name_base, const char*& _name);
......@@ -66,7 +67,6 @@ public:
virtual void emit_constructor(
const char* const _fnct, const Key& _obj, const DataVector& _args) = 0;
virtual void emit_destructor(const char* const _fnct, const Key& _obj) = 0;
void emit_destructor_and_unlink(const char* const _fnct, const Key& _obj);
virtual void emit_method_call(
const char* const _fnct, const Key& _obj, const DataVector& _args) = 0;
......@@ -104,9 +104,20 @@ protected:
private:
String jrnl_path_;
Base::OStringStream strm_;
size_t name_idx_;
std::set<String> name_book_; // currently booked unlinked names
std::map<Key, const char*> key_name_; // linked names
size_t name_idx_ = 0;
/*!
All currently booked names. This may contain names which haven't been linked
yet, thus it may have more entries than key_name_.
*/
std::set<String> name_book_;
/*!
A map between "keys" and "names" in the journal.
Keys are pointers or handles to object. This map links each key to a name,
which is the name of the variable used in the journal to represent the value.
All of the name char* pointers refer to entries in the Stream name book.
*/
std::map<Key, const char*> key_name_map_;
};
} // namespace Journal
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment