xref: /haiku/src/kits/support/BlockCache.cpp (revision 7120e97489acbf17d86d3f33e3b2e68974fd4b23)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		BlockCache.cpp
23 //	Author(s):		Massimiliano Origgi
24 //
25 //	Description:	Handles a cache of memory blocks of the same size
26 //------------------------------------------------------------------------------
27 
28 // Standard Includes -----------------------------------------------------------
29 #include <stdlib.h>
30 
31 // System Includes -------------------------------------------------------------
32 #include <Autolock.h>
33 #include <BlockCache.h>
34 
35 
36 // Private functions
37 static void *
38 object_alloc(size_t Size)
39 {
40 	return (void *)(new char[Size]);
41 }
42 
43 
44 static void
45 object_free(void *Data)
46 {
47 	delete[] Data;
48 }
49 
50 
51 static void*
52 malloc_alloc(size_t Size)
53 {
54 	return malloc(Size);
55 }
56 
57 
58 static void
59 malloc_free(void *Data)
60 {
61 	free(Data);
62 }
63 
64 
65 // Private structure for cache
66 struct _Block
67 {
68 	_Block(void);
69 	~_Block(void);
70 	void *Data;
71 	bool InUse;
72 };
73 
74 
75 _Block::_Block(void) :
76 	Data(NULL),
77 	InUse(false)
78 {
79 }
80 
81 
82 _Block::~_Block(void)
83 {
84 }
85 
86 
87 BBlockCache::BBlockCache(size_t CacheSize, size_t BlockSize, uint32 Type)
88 	:	fCacheSize(CacheSize),
89 		fBlockSize(BlockSize),
90 		fMark(0)
91 {
92 	// Setup function pointers based on Type
93 	if(Type == B_OBJECT_CACHE) {
94 		fAlloc = &object_alloc;
95 		fFree = &object_free;
96 	} else {
97 		fAlloc = &malloc_alloc;
98 		fFree = &malloc_free;
99 	}
100 
101 	// Allocate cache
102 	fCache = (void *)new _Block[CacheSize];
103 
104 	for(size_t i = 0; i < CacheSize; i++)
105 		((_Block *)fCache)[i].Data = fAlloc(BlockSize);
106 }
107 
108 
109 BBlockCache::~BBlockCache()
110 {
111 	delete[] fCache;
112 }
113 
114 
115 void *
116 BBlockCache::Get(size_t BlockSize)
117 {
118 	BAutolock lock(fLock);
119 
120 	if(BlockSize != fBlockSize)
121 		return fAlloc(BlockSize);
122 
123 	_Block *block;
124 	for(size_t i = fMark; i < fCacheSize; i++) {
125 		block = &((_Block *)fCache)[i];
126 		if(block->InUse == false) {
127 			block->InUse = true;
128 			++fMark;
129 			if(fMark == fCacheSize)
130 				fMark = 0;
131 			return block->Data;
132 		}
133 	}
134 
135 	if(fMark == 0)
136 		return fAlloc(BlockSize);
137 
138 	for(size_t i = 0; i < fMark; i++) {
139 		block = &((_Block *)fCache)[i];
140 		if(block->InUse == false) {
141 			block->InUse = true;
142 			++fMark;
143 			if(fMark == fCacheSize)
144 				fMark = 0;
145 			return block->Data;
146 		}
147 	}
148 
149 	return fAlloc(BlockSize);
150 }
151 
152 
153 void
154 BBlockCache::Save(void *Data, size_t BlockSize)
155 {
156 	BAutolock lock(fLock);
157 
158 	if(BlockSize != fBlockSize) {
159 		fFree(Data);
160 		return;
161 	}
162 
163 	_Block *block;
164 	for(size_t i = 0; i < fCacheSize; i++) {
165 		block = &((_Block *)fCache)[i];
166 		if(block->Data == Data) {
167 			block->InUse = false;
168 			fMark = i;
169 			return;
170 		}
171 	}
172 	fFree(Data);
173 }
174