summaryrefslogtreecommitdiffabout
path: root/lib/pointer_map.cc
blob: 44f7ebcd43cc4b56fd7f5d45e90b513a67b15922 (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
#include <cassert>
#include <map>
#include <string>
using namespace std;
#include "konforka/exception.h"
#include "konforka/pointer_map.h"

namespace konforka {

    /*
     * to_t->from_t->from->to
     */
    class mpointer_t {
	public:
	    void *ptr;
	    int ref;

	    mpointer_t() : ptr(0), ref(0) { }

	    void _ref() { ref++; }
	    void _unref() { ref--; }
    };
    typedef map<void*,mpointer_t> map_ptr_1_t;
    typedef map<string,map_ptr_1_t> map_ptr_2_t;
    typedef map<string,map_ptr_2_t> map_ptr_t;

    static map_ptr_t pointer_map;
    
    void _map_pointer(const type_info& tf,void *pf,const type_info& tt,void *pt) {
	mpointer_t& mpt = pointer_map[tf.name()][tt.name()][pf];
	if(mpt.ref) {
	    if(mpt.ptr != pt)
		throw exception(CODEPOINT,"trying to remap existing pointer with different value");
	}else{
	    mpt.ptr = pt;
	}
	mpt.ref++;
    }
    void _unmap_pointer(const type_info& tf,void *pf,const type_info& tt,void *pt) {
	map_ptr_t::iterator i1 = pointer_map.find(tf.name());
	if(i1==pointer_map.end())
	    throw exception(CODEPOINT,"no pointer of such type has ever been mapped");
	map_ptr_2_t::iterator i2 = i1->second.find(tt.name());
	if(i2==i1->second.end())
	    throw exception(CODEPOINT,"no pointer has ever been mapped to the object of this type");
	map_ptr_1_t::iterator i3 = i2->second.find(pf);
	if(i3==i2->second.end())
	    throw exception(CODEPOINT,"this pointer has never been mapped");
	assert(i3->second.ref>0);
	if(--(i3->second.ref))
	    return;
	i2->second.erase(i3);
	if(!i2->second.empty())
	    return;
	i1->second.erase(i2);
	if(!i1->second.empty())
	    return;
	pointer_map.erase(i1);
    }
    void *_mapped_pointer(const type_info& tf,void *pf,const type_info& tt) {
	map_ptr_t::iterator i1 = pointer_map.find(tf.name());
	if(i1==pointer_map.end())
	    throw exception(CODEPOINT,"no pointer of such type has ever been mapped");
	map_ptr_2_t::iterator i2 = i1->second.find(tt.name());
	if(i2==i1->second.end())
	    throw exception(CODEPOINT,"no pointer has ever been mapped to the object of this type");
	map_ptr_1_t::iterator i3 = i2->second.find(pf);
	if(i3==i2->second.end())
	    throw exception(CODEPOINT,"this pointer has never been mapped");
	assert(i3->second.ref>0);
	return i3->second.ptr;
    }

}