summaryrefslogtreecommitdiffabout
path: root/include/konforka/resource_pile.h
blob: d76a07bc12888062647325faa62eb7384585867d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifndef __KONFORKA_RESOURCE_PILE_H
#define __KONFORKA_RESOURCE_PILE_H

#include <map>
#include <konforka/responsible_wrapper.h>

/**
 * @file
 * @brief resource-piling base support.
 *
 * Base for implementing resource-piling.
 */

namespace konforka {
    using std::multimap;
    using std::pair;

    /**
     * @brief template base class for resource piling.
     *
     * @param key_t the type used for keying resources.
     * @param value_t the type of resource itself.
     * @param factory_t the factory class, providing value_t allocate(key_t)
     * static member.
     */
    template<typename key_t,typename value_t,typename factory_t>
	class resource_pile_base : public responsible_wrapper<value_t> {
	    /**
	     * @brief the type of the pile container itself.
	     */
	    typedef multimap<key_t,value_t> pile_t;
	    /*
	     * @brief the pile of resources.
	     */
	    static pile_t pile;
	    public:
	    /**
	     * @brief stored value for the key associated with the resource
	     * contained.
	     */
	    key_t _key;

	    /**
	     * @brief default constructor fetches or allocates resource.
	     *
	     * @param k the key for resource.
	     * @see allocate
	     */
	    resource_pile_base(const key_t& k) {
		allocate(k);
	    }
	    /**
	     * @brief destructor releases the resource back to pile.
	     */
	    virtual ~resource_pile_base() { this->drop(); }

	    /**
	     * @brief this is where the resource is handed back to pile.
	     */
	    void release() {
		pile.insert(pair<key_t,value_t>(_key,this->opkele));
	    }

	    /**
	     * @brief fetch from pile or allocate the resource.
	     *
	     * Try to see if we have a piled resource keyed to the argument. If
	     * we do -- fetch it from the pile, otherwise allocate anew.
	     *
	     * @param k the key for resource.
	     */
	    void allocate(const key_t& k) {
		this->drop();
		typename pile_t::iterator i = pile.find(k);
		if(i==pile.end()) {
		    this->attach(factory_t::allocate(k));
		}else{
		    this->attach(i->second);
		    try{ pile.erase(i); }catch(...){ _key = k; throw; }
		}
		_key = k;
	    }

	};

    template<typename key_t,typename value_t,typename factory_t>
	typename resource_pile_base<key_t,value_t,factory_t>::pile_t
	    resource_pile_base<key_t,value_t,factory_t>::pile;

    /**
     * @brief the generic single parameter new-based resource factory.
     *
     * The generic resource factory using new as a way to allocate resource
     * using the single-parameter constructor.
     *
     * @param key_t the key type.
     * @param value_t the resource type.
     *
     * @see resource_pile_base
     */
    template<typename key_t,typename value_t>
	struct resource_pile_generic_ptr_factory {
	    public:
		/**
		 * @brief allocate the resource using new.
		 *
		 * @param k the key.
		 * @return pointer to the newly allocated object.
		 */
		static value_t *allocate(const key_t& k) {
		    return new value_t(k);
		}
	};

}

#endif /* __KONFORKA_RESOURCE_PILE_H */
/* vim:set ft=cpp: */