xref: /haiku/src/kits/support/BlockCache.cpp (revision e01de52283efe0bd8fa107bd493df302c070204e)
1188ad70fSbeveloper /*
2188ad70fSbeveloper  * Copyright (c) 2003 Marcus Overhagen
3188ad70fSbeveloper  *
4188ad70fSbeveloper  * Permission is hereby granted, free of charge, to any person obtaining a
5188ad70fSbeveloper  * copy of this software and associated documentation files (the "Software"),
6188ad70fSbeveloper  * to deal in the Software without restriction, including without limitation
7188ad70fSbeveloper  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8188ad70fSbeveloper  * and/or sell copies of the Software, and to permit persons to whom the
9188ad70fSbeveloper  * Software is furnished to do so, subject to the following conditions:
10188ad70fSbeveloper  *
11188ad70fSbeveloper  * The above copyright notice and this permission notice shall be included in
12188ad70fSbeveloper  * all copies or substantial portions of the Software.
13188ad70fSbeveloper  *
14188ad70fSbeveloper  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15188ad70fSbeveloper  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16188ad70fSbeveloper  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17188ad70fSbeveloper  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18188ad70fSbeveloper  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19188ad70fSbeveloper  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20188ad70fSbeveloper  * DEALINGS IN THE SOFTWARE.
21188ad70fSbeveloper  */
22e75560e6Sejakowatz 
23c109ab72SStefano Ceccherini #include <BlockCache.h>
24188ad70fSbeveloper #include <Debug.h>
25188ad70fSbeveloper #include <string.h>
266cb536ddShaydentech #include <stdlib.h>
27188ad70fSbeveloper #include <new>
28c109ab72SStefano Ceccherini 
29*e01de522SMichael Lotz 
30188ad70fSbeveloper #define MAGIC1		0x9183f4d9
31188ad70fSbeveloper #define MAGIC2		0xa6b3c87d
32e75560e6Sejakowatz 
33*e01de522SMichael Lotz 
34340eed61SIngo Weinhold struct BBlockCache::_FreeBlock {
35340eed61SIngo Weinhold 	DEBUG_ONLY(	uint32		magic1;	)
36340eed61SIngo Weinhold 				_FreeBlock *next;
37340eed61SIngo Weinhold 	DEBUG_ONLY(	uint32		magic2;	)
38340eed61SIngo Weinhold };
39340eed61SIngo Weinhold 
40340eed61SIngo Weinhold 
41188ad70fSbeveloper // The requirements set by the BeBook's description of the destructor,
42188ad70fSbeveloper // as well as Get() function, allowing the caller to dispose of the
43188ad70fSbeveloper // memory, do not allow to allocate one large block to be used as pool.
44188ad70fSbeveloper // Thus we need to create multiple small ones.
45369eef13SIngo Weinhold // We maintain a list of free blocks.
46188ad70fSbeveloper 
BBlockCache(uint32 blockCount,size_t blockSize,uint32 allocationType)47*e01de522SMichael Lotz BBlockCache::BBlockCache(uint32 blockCount, size_t blockSize,
48188ad70fSbeveloper 	uint32 allocationType)
49*e01de522SMichael Lotz 	:
50*e01de522SMichael Lotz 	fFreeList(0),
51188ad70fSbeveloper 	fBlockSize(blockSize),
5216ce9822Sbeveloper 	fFreeBlocks(0),
53369eef13SIngo Weinhold 	fBlockCount(blockCount),
54a54e42d7Sbeveloper 	fLocker("some BBlockCache lock"),
55188ad70fSbeveloper 	fAlloc(0),
56188ad70fSbeveloper 	fFree(0)
57e75560e6Sejakowatz {
58188ad70fSbeveloper 	switch (allocationType) {
59188ad70fSbeveloper 		case B_OBJECT_CACHE:
60188ad70fSbeveloper 			fAlloc = &operator new[];
61188ad70fSbeveloper 			fFree = &operator delete[];
62188ad70fSbeveloper 			break;
63188ad70fSbeveloper 		case B_MALLOC_CACHE:
64a54e42d7Sbeveloper 		default:
65188ad70fSbeveloper 			fAlloc = &malloc;
66188ad70fSbeveloper 			fFree = &free;
67188ad70fSbeveloper 			break;
68e75560e6Sejakowatz 	}
69e75560e6Sejakowatz 
70188ad70fSbeveloper 	// To properly maintain a list of free buffers, a buffer must be
71188ad70fSbeveloper 	// large enough to contain the _FreeBlock struct that is used.
72188ad70fSbeveloper 	if (blockSize < sizeof(_FreeBlock))
73188ad70fSbeveloper 		blockSize = sizeof(_FreeBlock);
74c109ab72SStefano Ceccherini 
75ad159f43Sbeveloper 	// should have at least one block
76ad159f43Sbeveloper 	if (blockCount == 0)
77ad159f43Sbeveloper 		blockCount = 1;
78ad159f43Sbeveloper 
79188ad70fSbeveloper 	// create blocks and put them into the free list
806ecb8ce9Sbeveloper 	while (blockCount--) {
81188ad70fSbeveloper 		_FreeBlock *block = reinterpret_cast<_FreeBlock *>(fAlloc(blockSize));
82188ad70fSbeveloper 		if (!block)
83188ad70fSbeveloper 			break;
8416ce9822Sbeveloper 		fFreeBlocks++;
85188ad70fSbeveloper 		block->next = fFreeList;
86188ad70fSbeveloper 		fFreeList = block;
87188ad70fSbeveloper 		DEBUG_ONLY(block->magic1 = MAGIC1);
884ad0585eSUrias McCullough 		DEBUG_ONLY(block->magic2 = MAGIC2 + (uint32)(addr_t)block->next);
89e75560e6Sejakowatz 	}
90e75560e6Sejakowatz }
91e75560e6Sejakowatz 
92*e01de522SMichael Lotz 
~BBlockCache()93e75560e6Sejakowatz BBlockCache::~BBlockCache()
94e75560e6Sejakowatz {
95188ad70fSbeveloper 	// walk the free list and deallocate all blocks
96188ad70fSbeveloper 	fLocker.Lock();
97188ad70fSbeveloper 	while (fFreeList) {
98188ad70fSbeveloper 		ASSERT(fFreeList->magic1 == MAGIC1);
994ad0585eSUrias McCullough 		ASSERT(fFreeList->magic2 == MAGIC2 + (uint32)(addr_t)fFreeList->next);
100188ad70fSbeveloper 		void *pointer = fFreeList;
101188ad70fSbeveloper 		fFreeList = fFreeList->next;
102188ad70fSbeveloper 		DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
103188ad70fSbeveloper 		fFree(pointer);
104e75560e6Sejakowatz 	}
105188ad70fSbeveloper 	fLocker.Unlock();
106188ad70fSbeveloper }
107c109ab72SStefano Ceccherini 
108*e01de522SMichael Lotz 
109e75560e6Sejakowatz void *
Get(size_t blockSize)110188ad70fSbeveloper BBlockCache::Get(size_t blockSize)
111e75560e6Sejakowatz {
112188ad70fSbeveloper 	if (!fLocker.Lock())
113188ad70fSbeveloper 		return 0;
114188ad70fSbeveloper 	void *pointer;
115188ad70fSbeveloper 	if (blockSize == fBlockSize && fFreeList != 0) {
116188ad70fSbeveloper 		// we can take a block from the list
117188ad70fSbeveloper 		ASSERT(fFreeList->magic1 == MAGIC1);
1184ad0585eSUrias McCullough 		ASSERT(fFreeList->magic2 == MAGIC2 + (uint32)(addr_t)fFreeList->next);
119188ad70fSbeveloper 		pointer = fFreeList;
120188ad70fSbeveloper 		fFreeList = fFreeList->next;
121369eef13SIngo Weinhold 		fFreeBlocks--;
122188ad70fSbeveloper 		DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
123188ad70fSbeveloper 	} else {
124188ad70fSbeveloper 		if (blockSize < sizeof(_FreeBlock))
125188ad70fSbeveloper 			blockSize = sizeof(_FreeBlock);
126188ad70fSbeveloper 		pointer = fAlloc(blockSize);
127188ad70fSbeveloper 		DEBUG_ONLY(if (pointer) memset(pointer, 0xCC, sizeof(_FreeBlock)));
128e75560e6Sejakowatz 	}
129188ad70fSbeveloper 	fLocker.Unlock();
130188ad70fSbeveloper 	return pointer;
131e75560e6Sejakowatz }
132c109ab72SStefano Ceccherini 
133*e01de522SMichael Lotz 
134e75560e6Sejakowatz void
Save(void * pointer,size_t blockSize)135188ad70fSbeveloper BBlockCache::Save(void *pointer, size_t blockSize)
136e75560e6Sejakowatz {
137188ad70fSbeveloper 	if (!fLocker.Lock())
138e75560e6Sejakowatz 		return;
139369eef13SIngo Weinhold 	if (blockSize == fBlockSize && fFreeBlocks < fBlockCount) {
140188ad70fSbeveloper 		// the block needs to be returned to the cache
141188ad70fSbeveloper 		_FreeBlock *block = reinterpret_cast<_FreeBlock *>(pointer);
142188ad70fSbeveloper 		block->next = fFreeList;
143188ad70fSbeveloper 		fFreeList = block;
144369eef13SIngo Weinhold 		fFreeBlocks++;
145188ad70fSbeveloper 		DEBUG_ONLY(block->magic1 = MAGIC1);
1464ad0585eSUrias McCullough 		DEBUG_ONLY(block->magic2 = MAGIC2 + (uint32)(addr_t)block->next);
147188ad70fSbeveloper 	} else {
148188ad70fSbeveloper 		DEBUG_ONLY(memset(pointer, 0xCC, sizeof(_FreeBlock)));
149188ad70fSbeveloper 		fFree(pointer);
150e75560e6Sejakowatz 	}
151188ad70fSbeveloper 	fLocker.Unlock();
152e75560e6Sejakowatz }
153b93355abSbeveloper 
154*e01de522SMichael Lotz 
_ReservedBlockCache1()155b93355abSbeveloper void BBlockCache::_ReservedBlockCache1() {}
_ReservedBlockCache2()156b93355abSbeveloper void BBlockCache::_ReservedBlockCache2() {}
157