first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / configuration / ini_roller.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : ini_roller                                                        *
4 *  Author : Chris Koeritz                                                     *
5 *                                                                             *
6 *******************************************************************************
7 * Copyright (c) 2001-$now By Author.  This program is free software; you can  *
8 * redistribute it and/or modify it under the terms of the GNU General Public  *
9 * License as published by the Free Software Foundation; either version 2 of   *
10 * the License or (at your option) any later version.  This is online at:      *
11 *     http://www.fsf.org/copyleft/gpl.html                                    *
12 * Please send any updates to: fred@gruntose.com                               *
13 \*****************************************************************************/
14
15 #include "ini_roller.h"
16
17 #include <basis/astring.h>
18 #include <basis/functions.h>
19 #include <basis/mutex.h>
20 ///#include <structures/configurator.h>
21
22 using namespace basis;
23 using namespace structures;
24
25 namespace configuration {
26
27 //#define DEBUG_ID_GRANTING
28   // uncomment if you want verbose granting of unique ids.
29
30 const int ID_FACTOR = 28;
31   // this many ids are grabbed at once for eventual issuance.
32
33 ini_roller::ini_roller(configurator &config, const astring &section,
34     const astring &entry, int min, int max)
35 : _ini(config),
36   _ids(new int_roller(min, max)),
37   _section(new astring(section)),
38   _entry(new astring(entry)),
39   _lock(new mutex)
40 {
41   int current = _ini.load(section, entry, min);
42   _ids->set_current(current);
43   // make our first requisition of ids.  we start here rather than playing
44   // games with the next_id function.
45   _ini.store(section, entry, _ids->current() + ID_FACTOR);
46 }
47
48 ini_roller::~ini_roller()
49 {
50   // force the id to be past what we've allocated, but not too far past.
51   _ini.store(*_section, *_entry, _ids->current() + 1);
52   WHACK(_ids);
53   WHACK(_section);
54   WHACK(_entry);
55   WHACK(_lock);
56 }
57
58 int ini_roller::current_id() const
59 {
60   auto_synchronizer l(*_lock);
61   return _ids->current();
62 }
63
64 int ini_roller::next_id()
65 {
66 #ifdef DEBUG_ID_GRANTING
67   FUNCDEF("next_id");
68 #endif
69   auto_synchronizer l(*_lock);
70   int to_return = _ids->current();
71
72   // this uses a relaxed id issuance policy; the id that's in the INI
73   // file is only updated when we run out of the range that we allocate for it.
74   // the roller's current value is used whenever issuing an id, but next_id()
75   // is always called before that id is actually issued.
76
77   if ( (_ids->current() < _ids->maximum() - 2) 
78       && (_ids->current() % ID_FACTOR) ) {
79     // no id range grabbing needed yet and no rollover.
80     _ids->next_id();
81 #ifdef DEBUG_ID_GRANTING
82     LOG(astring(astring::SPRINTF, "standard id issue: %d.", to_return));
83 #endif
84     return to_return;
85   }
86
87   // now we need to allocate a new range of ids...  and store in ini.
88   int new_range = to_return + ID_FACTOR;
89 #ifdef DEBUG_ID_GRANTING
90   LOG(astring(astring::SPRINTF, "finding next range, new start in ini "
91       "is: %d.", new_range));
92 #endif
93   // if the id wraps around, reset it.
94   if ( (new_range < 0) || (new_range >= _ids->maximum()) )
95     new_range = ID_FACTOR;
96 #ifdef DEBUG_ID_GRANTING
97   LOG(astring(astring::SPRINTF, "after check, new ini id is: %d.",
98       new_range));
99 #endif
100   _ini.store(*_section, *_entry, new_range);
101     // set the next stored id to the block above where we're using.
102   _ids->next_id();  // jump to the next one in the range.
103 #ifdef DEBUG_ID_GRANTING
104   LOG(astring(astring::SPRINTF, "after store, id is: %d.", to_return));
105 #endif
106   return to_return;
107 }
108
109 } //namespace.
110