Checkpoint - more work done.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1685 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Phipps
2002-10-26 18:55:44 +00:00
parent 4b8670624a
commit 3dcf5034e5
7 changed files with 226 additions and 50 deletions
+53 -28
View File
@@ -1,64 +1,89 @@
#ifndef _HASH_H #ifndef _HASH_H
#define _HASH_H #define _HASH_H
#include "list.h" #include "list.h"
#include "vm.h"
#include "page.h"
#include "pageManager.h"
#include "vmHeaderBlock.h"
#include <new.h>
static bool throwException (node &foo) extern vmHeaderBlock *vmBlock;
{ throw ("Attempting to use an hash table without setting up a 'hash' function"); }
class hashTable : public list class hashTable : public list
{ {
public: public:
hashTable(int size) hashTable(int size) {
{
nodeCount=0; nodeCount=0;
numRocks=size; numRocks=size;
int pageCount=PAGE_SIZE*size/sizeof(list);
if (size*sizeof (list *)>PAGE_SIZE)
throw ("Hash table too big!");
page *newPage=vmBlock->pageMan->getPage(); page *newPage=vmBlock->pageMan->getPage();
if (!newPage) if (!newPage)
throw ("Out of pages to allocate a pool!"); throw ("Out of pages to allocate a pool!");
int newCount=PAGE_SIZE/sizeof(area); rocks=(list **)(newPage->getAddress());
acquire_sem(inUse);
//error ("poolarea::get: Adding %d new elements to the pool!\n",newCount); int listsPerPage=PAGE_SIZE/sizeof(list);
for (int i=0;i<newCount;i++) int pages=(size+(listsPerPage-1))/listsPerPage;
unused.add(((node *)(newPage->getAddress()+(i*sizeof(area))))); for (int pageCount=0;pageCount<pages;pageCount++)
release_sem(inUse); {
page *newPage=vmBlock->pageMan->getPage();
if (!newPage)
throw ("Out of pages to allocate a pool!");
for (int i=0;i<listsPerPage;i++)
rocks[i]=new ((list *)(newPage->getAddress()+(i*sizeof(list)))) list;
}
} }
void setHash (ulong (*hash_in)(node &)) { hash=hash_in; } void setHash (ulong (*hash_in)(node &)) { hash=hash_in; }
void setIsEqual (ulong (*isEqual_in)(node &,node &)) { isEqual=isEqual_in; } void setIsEqual (bool (*isEqual_in)(node &,node &)) { isEqual=isEqual_in; }
int count(void) {return nodeCount;} int count(void) {return nodeCount;}
void add (node *newNode) { void add (node *newNode) {
if (!hash)
throw ("Attempting to use a hash table without setting up a 'hash' function");
unsigned long hashValue=hash(*newNode)%numRocks; unsigned long hashValue=hash(*newNode)%numRocks;
// Note - no looking for duplicates; no ordering. // Note - no looking for duplicates; no ordering.
rocks[hashValue].add(newNode); rocks[hashValue]->add(newNode);
} }
node *next(void) { return NULL; // This operation doesn't make sense for this class}
void remove(node *toNuke) node *next(void) {throw ("Next is invalid in a hash table!");} // This operation doesn't make sense for this class
{
unsigned long hashValue=hash(*findNode)%numRocks; void remove(node *toNuke) {
rocks[hashValue].remove(newNode); if (!hash)
throw ("Attempting to use a hash table without setting up a 'hash' function");
unsigned long hashValue=hash(*toNuke)%numRocks;
rocks[hashValue]->remove(toNuke);
} }
void dump(void)
{ void dump(void) {
for (int i=0;i<numRocks;i++) for (int i=0;i<numRocks;i++)
for (struct node *cur=rocks[hashValue].rock;cur && !done;cur=cur->next) for (struct node *cur=rocks[i]->rock;cur;cur=cur->next)
error ("hashTable::dump: At %p, next = %p\n",cur,cur->next); error ("hashTable::dump: On bucket %d of %d, At %p, next = %p\n",i,numRocks,cur,cur->next);
} }
node *find(node *findNode)
{ bool ensureSane (void) {
bool ok=true;
for (int i=0;i<numRocks;i++)
ok|=rocks[i]->ensureSane();
return ok;
}
node *find(node *findNode) {
if (!hash)
throw ("Attempting to use a hash table without setting up a 'hash' function");
if (!isEqual)
throw ("Attempting to use a hash table without setting up an 'isEqual' function");
unsigned long hashValue=hash(*findNode)%numRocks; unsigned long hashValue=hash(*findNode)%numRocks;
for (struct node *cur=rocks[hashValue].rock;cur && !done;cur=cur->next) for (struct node *cur=rocks[hashValue]->rock;cur ;cur=cur->next)
if (isEqual(*findNode,*cur)) if (isEqual(*findNode,*cur))
return cur; return cur;
return NULL; return NULL;
} }
private: private:
ulong (*hash)(node &a); ulong (*hash)(node &a);
bool (*isEqual)(node &a,node &b); bool (*isEqual)(node &a,node &b);
list *rocks; list **rocks;
int numRocks; int numRocks;
}; };
#endif #endif
+107
View File
@@ -0,0 +1,107 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "hashTable.h"
#include "OS.h"
#include "vmInterface.h"
vmInterface vm(30);
struct hashTest : public node {
hashTest(int i) {value=i;}
int value;
};
ulong hash(node &a) {
hashTest &a1=reinterpret_cast<hashTest &>(a);
return a1.value;
}
bool isEqual (node &a,node &b) {
hashTest &a1=reinterpret_cast<hashTest &>(a);
hashTest &b1=reinterpret_cast<hashTest &>(b);
return (a1.value==b1.value);
}
int main(int argc,char **argv) {
// Test 1 - Try to add to foo without setting an isLessThan function
try {
hashTable foo(10);
node tmp;
foo.add(&tmp);
}
catch (const char *badness)
{
if (strcmp(badness,"Attempting to use a hash table without setting up a 'hash' function"))
error ("Failure on adding with no hash, error = %s\n", badness);
error ("Success on adding with no hash, \n" );
}
catch(...)
{
error ("Failure on adding with no hash, unknown exception\n");
}
hashTable foo(20);
foo.setHash(hash);
foo.setIsEqual(isEqual);
error ("Add the first couple, in order (easy)\n");
hashTest first(1);
foo.add(&first);
hashTest second(2);
foo.add(&second);
foo.dump();
error ("Add the next three, not in order (harder)\n");
hashTest third(3);
hashTest fourth(4);
hashTest fifth(5);
foo.add(&fourth);
foo.add(&third);
foo.add(&fifth);
foo.dump();
error ("Create bar, populated with 1000 values");
hashTable bar(200);
bar.setHash(hash);
bar.setIsEqual(isEqual);
for (int a=0;a<100;a++)
bar.add(new hashTest(a));
for (int a=1000;a>=100;a--)
bar.add(new hashTest(a));
bar.dump();
error ("Removing simple case: remove 1,leave 2,3,4,5 \n");
foo.remove(&first);
foo.dump();
error ("Removing simple case: remove 2,leave 3,4,5 \n");
foo.remove(&second);
foo.dump();
error ("Setting up middle case (readding 1 and 2)\n");
foo.add(&first);
foo.add(&second);
foo.dump();
error ("Removing middle case (removing 2)\n");
foo.remove(&second);
foo.dump();
error ("Removing middle case (removing 1)\n");
foo.remove(&first);
foo.dump();
error ("Finding 1\n");
hashTest findOne(1);
hashTest *found=(hashTest *)bar.find(&findOne);
error ("found value = %d\n",found->value);
error ("Finding 77\n");
hashTest findSeventySeven(77);
hashTest *found77=(hashTest *)bar.find(&findSeventySeven);
error ("found value = %d\n",found77->value);
error ("ensuringSane on smaller (foo) = %s\n",((foo.ensureSane())?"OK":"BAD!"));
error ("ensuringSane on larger (bar) = %s\n",((bar.ensureSane())?"OK":"BAD!"));
return 0;
}
+23 -18
View File
@@ -13,41 +13,34 @@ struct node
class list { class list {
public: public:
list(void){nodeCount=0;rock=NULL;} list(void){nodeCount=0;rock=NULL;}
void add (node *newNode) void add (node *newNode) {
{
newNode->next=rock; newNode->next=rock;
rock=newNode; rock=newNode;
nodeCount++; nodeCount++;
} }
//int count(void) {error ("list::count: About to return %d\n",nodeCount);return nodeCount;} //int count(void) {error ("list::count: About to return %d\n",nodeCount);return nodeCount;}
int count(void) {return nodeCount;} int count(void) {return nodeCount;}
node *next(void) node *next(void) {
{
//dump(); //dump();
node *n=rock; node *n=rock;
if (rock) if (rock) {
{
rock=rock->next; rock=rock->next;
nodeCount--; nodeCount--;
} }
//dump(); //dump();
return n; return n;
} }
void remove(node *toNuke) void remove(node *toNuke) {
{
//error ("list::remove starting: nuking %x \n",toNuke); //error ("list::remove starting: nuking %x \n",toNuke);
//dump(); //dump();
if (rock==toNuke) if (rock==toNuke) {
{
rock=rock->next; rock=rock->next;
nodeCount--; nodeCount--;
} }
else else {
{
bool done=false; bool done=false;
for (struct node *cur=rock;!done && cur->next;cur=cur->next) for (struct node *cur=rock;!done && cur->next;cur=cur->next)
if (cur->next==toNuke) if (cur->next==toNuke) {
{
cur->next=toNuke->next; cur->next=toNuke->next;
nodeCount--; nodeCount--;
done=true; done=true;
@@ -56,13 +49,25 @@ class list {
//error ("list::remove ending: \n"); //error ("list::remove ending: \n");
//dump(); //dump();
} }
void dump(void) void dump(void) {
{
for (struct node *cur=rock;cur;cur=cur->next) for (struct node *cur=rock;cur;cur=cur->next)
{ { error ("list::dump: At %p, next = %p\n",cur,cur->next); }
error ("list::dump: At %p, next = %p\n",cur,cur->next);
} }
bool ensureSane (void) {
int temp=nodeCount;
for (struct node *cur=rock;cur && --temp;cur=cur->next) ; // Intentional to have no body
if (temp<0) {
error ("list::ensureSane: found too many records!\n");
return false;
} }
if (temp>0) {
error ("list::ensureSane: found too few records!\n");
return false;
}
return true;
}
struct node *rock; struct node *rock;
int nodeCount; int nodeCount;
private: private:
+36
View File
@@ -1,6 +1,7 @@
#include "pageManager.h" #include "pageManager.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
void *addOffset(void *base,unsigned long offset) void *addOffset(void *base,unsigned long offset)
{ {
@@ -74,6 +75,41 @@ page *pageManager::getPage(void)
return ret; return ret;
} }
bool pageManager::getContiguousPages(int pages,page **location)
{
unsigned long current, start=0, next;
page *curPage;
int count=0;
while (count<pages)
{
curPage=getPage();
current=curPage->getAddress();
if (start==0)
{
start=current;
location[count++]=curPage;
}
else if (current==start+PAGE_SIZE*count) // This is the next one in line
location[count++]=curPage;
else if (current==start-PAGE_SIZE) // Found the one directly previous
{
memmove(location[1],location[0],count*sizeof(page *));
start=current;
location[0]=curPage;
count++;
}
else // Forget this series - it doesn't seem to be going anywhere...
{
while (--count>=0)
{
freePage(location[count]);
location[count]=NULL;
}
}
}
return true;
}
void pageManager::freePage(page *toFree) void pageManager::freePage(page *toFree)
{ {
error ("pageManager::freePage; old value = %d\n",toFree->count); error ("pageManager::freePage; old value = %d\n",toFree->count);
+1
View File
@@ -9,6 +9,7 @@ class pageManager {
pageManager(void); pageManager(void);
void setup(void *memory,int pages); void setup(void *memory,int pages);
page *getPage(void); page *getPage(void);
bool getContiguousPages(int pages,page **location);
void freePage(page *); void freePage(page *);
void cleaner(void); void cleaner(void);
int desperation(void); int desperation(void);
+1
View File
@@ -21,6 +21,7 @@ class vpage : public node
void flush(void); // write page to vnode, if necessary void flush(void); // write page to vnode, if necessary
void refresh(void); // Read page back in from vnode void refresh(void); // Read page back in from vnode
vpage(void); vpage(void);
// Setup should now only be called by the vpage manager...
void setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state); // backing and/or physMem can be NULL/0. void setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state); // backing and/or physMem can be NULL/0.
void cleanup(void); void cleanup(void);
void setProtection(protectType prot); void setProtection(protectType prot);
+1
View File
@@ -14,6 +14,7 @@ class vpageManager
private: private:
public: public:
vpage *getVpage(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state);
vpage *getVpage(vnode &vn); vpage *getVpage(vnode &vn);
void putVpage(vpage &vp); void putVpage(vpage &vp);
} }