It has been a while since I last worked on Aesalon proper.
[aesalon.git] / module / modules / dynamicMemory / renderer / DataCache.cpp
blob93b20f948841762eac0f32be7ea8f67847e45cdf
1 #include <iostream>
2 #include <string.h>
3 #include <algorithm>
5 #include "DataCache.h"
7 DynamicMemoryDataCache::DynamicMemoryDataCache() {
8 m_treeHeadVector.push_back(new TreeHead(0));
9 std::cout << "m_treeHeadVector.size(): " << m_treeHeadVector.size() << std::endl;
12 DynamicMemoryDataCache::~DynamicMemoryDataCache() {
16 void DynamicMemoryDataCache::processPacket(DataPacket *packet) {
17 uint8_t type = *(uint8_t *)packet->data;
19 if(type == 0) {
20 uint64_t address;
21 memcpy(&address, (uint8_t *)packet->data + 1, sizeof(address));
22 uint64_t nmemb, size;
23 memcpy(&nmemb, (uint8_t *)packet->data + 9, sizeof(nmemb));
24 memcpy(&size, (uint8_t *)packet->data + 17, sizeof(size));
25 allocBlock(address, nmemb * size, packet->dataSource.timestamp);
27 else if(type == 1) {
28 uint64_t address;
29 memcpy(&address, (uint8_t *)packet->data + 1, sizeof(address));
30 uint64_t size;
31 memcpy(&size, (uint8_t *)packet->data + 9, sizeof(size));
33 /*std::cout << "malloc(" << size << "): 0x" << std::hex << address << std::dec << std::endl;*/
34 allocBlock(address, size, packet->dataSource.timestamp);
36 else if(type == 2) {
37 uint64_t address;
38 memcpy(&address, (uint8_t *)packet->data + 1, sizeof(address));
39 /*std::cout << "free(0x" << std::hex << address << std::dec << ")" << std::endl;*/
41 freeBlock(address, packet->dataSource.timestamp);
43 else if(type == 3) {
44 /* TODO: implement this. */
45 std::cout << "realloc currently NYI." << std::endl;
48 /* TODO: softcode this limit. */
49 if(latestTree()->changedList().size() > 500) {
50 std::cout << ">500 events in tree, creating new head . . ." << std::endl;
51 newHead();
55 static bool compareHeads(TreeHead *one, TreeHead *two) {
56 return one->timestamp() < two->timestamp();
59 static bool compareBlocks(Block *one, Block *two) {
60 return one->allocTime() < two->allocTime();
63 void DynamicMemoryDataCache::visit(const DataRange &dataRange, CacheVisitor *visitor) {
64 TreeHead th(-1);
65 th.updateTimestamp(dataRange.beginTime());
66 TreeHeadVector::const_iterator startHead = std::lower_bound(m_treeHeadVector.begin(), m_treeHeadVector.end(), &th, compareHeads);
68 if(startHead == m_treeHeadVector.end()) {
69 /* The range is out of range. */
70 return;
73 th.updateTimestamp(dataRange.endTime());
74 TreeHeadVector::const_iterator endHead = std::upper_bound(m_treeHeadVector.begin(), m_treeHeadVector.end(), &th, compareHeads);
76 class RecursiveTraversal {
77 public:
78 CacheVisitor *m_visitor;
79 Timestamp m_lowerCutoff;
80 Timestamp m_upperCutoff;
82 void traverse(TreeNode *node) {
83 if(node == NULL) return;
85 if(node->left()) traverse(node->left());
86 if(node->right()) traverse(node->right());
87 if(node->data()) {
88 Block *block = node->data();
89 if(!(block->allocTime() > m_upperCutoff
90 || block->releaseTime() < m_lowerCutoff)) m_visitor->handleBlock(node->data());
93 } traverser;
95 traverser.m_lowerCutoff = dataRange.beginTime();
96 traverser.m_upperCutoff = dataRange.endTime();
97 traverser.m_visitor = visitor;
99 traverser.traverse((*startHead)->headNode());
101 Block block(0, 0, dataRange.beginTime());
103 TreeHead::BlockList::const_iterator start = std::lower_bound((*startHead)->changedList().begin(), (*startHead)->changedList().end(), &block, compareBlocks);
105 for(; start != (*startHead)->changedList().end(); start ++) {
106 visitor->handleBlock((*start));
109 if(startHead == endHead) return;
111 ++ startHead;
113 for(; startHead != endHead; startHead ++) {
114 for(TreeHead::BlockList::const_iterator i = (*startHead)->changedList().begin();
115 i != (*startHead)->changedList().end() && (*i)->allocTime() < dataRange.endTime(); i ++) {
117 visitor->handleBlock(*i);
123 void DynamicMemoryDataCache::newHead() {
124 TreeHead *head = new TreeHead(m_treeHeadVector.size());
125 head->attachTo(m_treeHeadVector.back());
126 m_treeHeadVector.push_back(head);
129 void DynamicMemoryDataCache::allocBlock(uint64_t address, uint64_t size, Timestamp timestamp) {
130 TreeNode *node = latestTree()->create(address);
132 if(node == NULL) {
133 newHead();
134 node = latestTree()->create(address);
137 Block *block = new Block(address, size, timestamp);
139 node->setData(block);
140 latestTree()->appendChanged(block);
141 latestTree()->updateTimestamp(timestamp);
144 void DynamicMemoryDataCache::freeBlock(uint64_t address, Timestamp timestamp) {
145 TreeNode *node = latestTree()->lookup(address);
146 if(node == NULL) return;
147 if(!latestTree()->remove(address)) {
148 newHead();
149 latestTree()->remove(address);
151 node->data()->setReleaseTime(timestamp);
152 latestTree()->appendChanged(node->data());
153 latestTree()->updateTimestamp(timestamp);
156 DataRange DynamicMemoryDataCache::densityRange() const {
157 /* TODO: calculate total time and data range. (step through each?) */
158 return DataRange(m_treeHeadVector.front()->changedList().front()->allocTime(), m_treeHeadVector.front()->changedList().front()->address(),
159 m_treeHeadVector.front()->changedList().front()->releaseTime(), m_treeHeadVector.front()->changedList().front()->address() + m_treeHeadVector.front()->changedList().front()->size() + 128);