Added a facility for handling scoped executions.

This commit is contained in:
John Wiegley 2007-05-07 10:24:55 +00:00
parent 65e4fc7ebf
commit 8aada79971
4 changed files with 94 additions and 44 deletions

73
src/scoped_execute.h Normal file
View file

@ -0,0 +1,73 @@
#ifndef _SCOPE_EXECUTE_H
#define _SCOPE_EXECUTE_H
template <typename T>
class scoped_variable : public boost::noncopyable
{
T& var;
T prev;
bool enabled;
public:
explicit scoped_variable(T& _var)
: var(_var), prev(var), enabled(true) {}
explicit scoped_variable(T& _var, const T& value)
: var(_var), prev(var), enabled(true) {
var = value;
}
~scoped_variable() {
if (enabled)
var = prev;
}
void clear() {
enabled = false;
}
};
template <typename T>
class scoped_execute : public boost::noncopyable
{
typedef boost::function<void (T)> function_t;
function_t code;
T arg;
bool enabled;
public:
explicit scoped_execute(const function_t& _code, T _arg)
: code(_code), arg(_arg), enabled(true) {}
~scoped_execute() {
if (enabled)
code(arg);
}
void clear() {
enabled = false;
}
};
template <>
class scoped_execute<void> : public boost::noncopyable
{
typedef boost::function<void ()> function_t;
function_t code;
bool enabled;
public:
explicit scoped_execute(const function_t& _code)
: code(_code), enabled(true) {}
~scoped_execute() {
if (enabled)
code();
}
void clear() {
enabled = false;
}
};
#endif // _SCOPE_EXECUTE_H

View file

@ -103,22 +103,13 @@ journal_t * session_t::read_data(const string& master_account)
DEBUG("ledger.cache", "using_cache " << cache_file->string());
cache_dirty = true;
if (exists(*cache_file)) {
scoped_variable<optional<path> >
save_price_db(journal->price_db, price_db);
ifstream stream(*cache_file);
optional<path> price_db_orig = journal->price_db;
try {
journal->price_db = price_db;
entry_count += read_journal(stream, journal, NULL, data_file);
if (entry_count > 0)
cache_dirty = false;
journal->price_db = price_db_orig;
}
catch (...) {
journal->price_db = price_db_orig;
throw;
}
entry_count += read_journal(stream, journal, NULL, data_file);
if (entry_count > 0)
cache_dirty = false;
}
}

View file

@ -10,7 +10,8 @@ static unsigned int linenum;
static unsigned int src_idx;
static accounts_map account_aliases;
static std::list<std::pair<path, int> > include_stack;
typedef std::list<std::pair<path, int> > include_stack_t;
static include_stack_t include_stack;
#define TIMELOG_SUPPORT 1
#ifdef TIMELOG_SUPPORT
@ -508,14 +509,6 @@ entry_t * parse_entry(std::istream& in, char * line, journal_t * journal,
return curr.release();
}
template <typename T>
struct push_var {
T& var;
T prev;
push_var(T& _var) : var(_var), prev(var) {}
~push_var() { var = prev; }
};
static inline void parse_symbol(char *& p, string& symbol)
{
if (*p == '"') {
@ -836,11 +829,11 @@ unsigned int textual_parser_t::parse(std::istream& in,
char * p = next_element(line);
string word(line + 1);
if (word == "include") {
push_var<path> save_path(pathname);
push_var<unsigned int> save_src_idx(src_idx);
push_var<unsigned long> save_beg_pos(beg_pos);
push_var<unsigned long> save_end_pos(end_pos);
push_var<unsigned int> save_linenum(linenum);
scoped_variable<path> save_path(pathname);
scoped_variable<unsigned int> save_src_idx(src_idx);
scoped_variable<unsigned long> save_beg_pos(beg_pos);
scoped_variable<unsigned long> save_end_pos(end_pos);
scoped_variable<unsigned int> save_linenum(linenum);
if (*p != '~' && *p != '/')
pathname = (pathname.branch_path() / path(p)).normalize();
@ -850,18 +843,14 @@ unsigned int textual_parser_t::parse(std::istream& in,
DEBUG("ledger.textual.include", "Line " << linenum << ": " <<
"Including path '" << pathname.string() << "'");
scoped_execute<void>
pop_include_stack(boost::bind(&include_stack_t::pop_back,
boost::ref(include_stack)));
include_stack.push_back
(std::pair<path, int>(journal->sources.back(), linenum - 1));
try {
count += journal->session->read_journal(pathname, journal,
account_stack.front());
include_stack.pop_back();
}
catch (...) {
include_stack.pop_back();
throw;
}
count += journal->session->read_journal(pathname, journal,
account_stack.front());
}
else if (word == "account") {
if (account_t * acct = account_stack.front()->find_account(p))

View file

@ -441,16 +441,13 @@ inline void throw_unexpected_error(char c, char wanted) {
/**********************************************************************
*
* Date/time support classes
* General support for objects with "flags"
* Support for scoped execution and variable restoration
*/
#include "times.h"
/**********************************************************************
*
* General support for objects with "flags"
*/
#include "flags.h"
#include "scoped_execute.h"
/**********************************************************************
*