Got rid of the List template class in the disk device manager source dir. Instead we use the Vector based Kernel Utils classes now. Various related changes.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3810 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
aabf9e6b16
commit
5b489f6f16
@ -4,7 +4,6 @@
|
||||
#define _K_DISK_DEVICE_MANAGER_H
|
||||
|
||||
#include "disk_device_manager.h"
|
||||
#include "List.h"
|
||||
#include "Locker.h"
|
||||
|
||||
namespace BPrivate {
|
||||
@ -58,7 +57,7 @@ public:
|
||||
|
||||
// manager must be locked
|
||||
int32 CountDevices();
|
||||
KDiskDevice *DeviceAt(int32 index);
|
||||
KDiskDevice *NextDevice(int32 *cookie);
|
||||
|
||||
bool PartitionAdded(KPartition *partition); // implementation internal
|
||||
bool PartitionRemoved(KPartition *partition); //
|
||||
@ -82,7 +81,7 @@ public:
|
||||
KDiskSystem *DiskSystemWithName(const char *name);
|
||||
KDiskSystem *DiskSystemWithID(disk_system_id id);
|
||||
int32 CountDiskSystems();
|
||||
KDiskSystem *DiskSystemAt(int32 index);
|
||||
KDiskSystem *NextDiskSystem(int32 *cookie);
|
||||
|
||||
KDiskSystem *LoadDiskSystem(disk_system_id id);
|
||||
KDiskSystem *LoadNextDiskSystem(int32 *cookie);
|
||||
@ -106,11 +105,16 @@ private:
|
||||
status_t _ScanDevice(KDiskDevice *device);
|
||||
status_t _ScanPartition(KPartition *partition);
|
||||
|
||||
struct DeviceMap;
|
||||
struct DiskSystemMap;
|
||||
struct PartitionMap;
|
||||
struct PartitionSet;
|
||||
|
||||
BLocker fLock;
|
||||
List<KDiskDevice*> fDevices; // TODO: Optimize!
|
||||
List<KPartition*> fPartitions; //
|
||||
List<KDiskSystem*> fDiskSystems; //
|
||||
List<KPartition*> fObsoletePartitions; //
|
||||
DeviceMap *fDevices;
|
||||
PartitionMap *fPartitions;
|
||||
DiskSystemMap *fDiskSystems;
|
||||
PartitionSet *fObsoletePartitions;
|
||||
|
||||
static KDiskDeviceManager *fDefaultManager;
|
||||
};
|
||||
|
@ -3,8 +3,9 @@
|
||||
#ifndef _K_DISK_DEVICE_PARTITION_H
|
||||
#define _K_DISK_DEVICE_PARTITION_H
|
||||
|
||||
#include <Vector.h>
|
||||
|
||||
#include "disk_device_manager.h"
|
||||
#include "List.h"
|
||||
|
||||
// partition flags
|
||||
// TODO: move to another header (must be accessible from userland API impl.)
|
||||
@ -164,8 +165,10 @@ private:
|
||||
static int32 _NextID();
|
||||
|
||||
protected:
|
||||
typedef Vector<KPartition*> PartitionVector;
|
||||
|
||||
partition_data fPartitionData;
|
||||
List<KPartition*> fChildren;
|
||||
PartitionVector fChildren;
|
||||
KDiskDevice *fDevice;
|
||||
KPartition *fParent;
|
||||
KDiskSystem *fDiskSystem;
|
||||
|
@ -5,6 +5,7 @@ SEARCH_SOURCE += [ FDirName $(OBOS_TOP) src kits storage ] ;
|
||||
# DiskDeviceTypes.cpp
|
||||
|
||||
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
||||
UsePrivateHeaders [ FDirName kernel util ] ;
|
||||
UsePrivateHeaders [ FDirName shared ] ;
|
||||
UsePrivateHeaders [ FDirName storage ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src tests kits storage virtualdrive ] ;
|
||||
|
@ -8,6 +8,9 @@
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <VectorMap.h>
|
||||
#include <VectorSet.h>
|
||||
|
||||
#include "KDiskDevice.h"
|
||||
#include "KDiskDeviceManager.h"
|
||||
#include "KDiskDeviceUtils.h"
|
||||
@ -30,14 +33,56 @@ using BPrivate::DiskDevice::KDiskDeviceJobQueue;
|
||||
static const char *kPartitioningSystemPrefix = "partitioning_systems";
|
||||
static const char *kFileSystemPrefix = "file_systems";
|
||||
|
||||
// GetPartitionID
|
||||
struct GetPartitionID {
|
||||
inline partition_id operator()(const KPartition *partition) const
|
||||
{
|
||||
return partition->ID();
|
||||
}
|
||||
};
|
||||
|
||||
// GetDiskSystemID
|
||||
struct GetDiskSystemID {
|
||||
inline disk_system_id operator()(const KDiskSystem *system) const
|
||||
{
|
||||
return system->ID();
|
||||
}
|
||||
};
|
||||
|
||||
// PartitionMap
|
||||
struct KDiskDeviceManager::PartitionMap : VectorMap<partition_id, KPartition*,
|
||||
VectorMapEntryStrategy::ImplicitKey<partition_id, KPartition*,
|
||||
GetPartitionID> > {
|
||||
};
|
||||
|
||||
// DeviceMap
|
||||
struct KDiskDeviceManager::DeviceMap : VectorMap<partition_id, KDiskDevice*,
|
||||
VectorMapEntryStrategy::ImplicitKey<partition_id, KDiskDevice*,
|
||||
GetPartitionID> > {
|
||||
};
|
||||
|
||||
// DiskSystemMap
|
||||
struct KDiskDeviceManager::DiskSystemMap : VectorMap<disk_system_id,
|
||||
KDiskSystem*,
|
||||
VectorMapEntryStrategy::ImplicitKey<disk_system_id, KDiskSystem*,
|
||||
GetDiskSystemID> > {
|
||||
};
|
||||
|
||||
// PartitionSet
|
||||
struct KDiskDeviceManager::PartitionSet : VectorSet<KPartition*> {
|
||||
};
|
||||
|
||||
|
||||
// constructor
|
||||
KDiskDeviceManager::KDiskDeviceManager()
|
||||
: fLock("disk device manager"),
|
||||
fDevices(20),
|
||||
fPartitions(100),
|
||||
fDiskSystems(20),
|
||||
fObsoletePartitions(20)
|
||||
fDevices(new(nothrow) DeviceMap),
|
||||
fPartitions(new(nothrow) PartitionMap),
|
||||
fDiskSystems(new(nothrow) DiskSystemMap),
|
||||
fObsoletePartitions(new(nothrow) PartitionSet)
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return;
|
||||
// add partitioning systems
|
||||
if (void *list = open_module_list(kPartitioningSystemPrefix)) {
|
||||
char moduleName[B_PATH_NAME_LENGTH];
|
||||
@ -68,41 +113,44 @@ DBG(OUT("number of disk systems: %ld\n", CountDiskSystems()));
|
||||
KDiskDeviceManager::~KDiskDeviceManager()
|
||||
{
|
||||
// remove all devices
|
||||
int32 count = CountDevices();
|
||||
for (int32 i = count - 1; i >= 0; i--) {
|
||||
if (KDiskDevice *device = DeviceAt(i)) {
|
||||
PartitionRegistrar _(device);
|
||||
_RemoveDevice(device);
|
||||
}
|
||||
for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie);) {
|
||||
PartitionRegistrar _(device);
|
||||
_RemoveDevice(device);
|
||||
}
|
||||
// some sanity checks
|
||||
if (fPartitions.CountItems() > 0) {
|
||||
if (fPartitions->Count() > 0) {
|
||||
DBG(OUT("WARNING: There are still %ld unremoved partitions!\n",
|
||||
fPartitions.CountItems()));
|
||||
fPartitions->Count()));
|
||||
}
|
||||
if (fObsoletePartitions.CountItems() > 0) {
|
||||
if (fObsoletePartitions->Count() > 0) {
|
||||
DBG(OUT("WARNING: There are still %ld obsolete partitions!\n",
|
||||
fObsoletePartitions.CountItems()));
|
||||
fObsoletePartitions->Count()));
|
||||
}
|
||||
// remove all disk systems
|
||||
count = CountDiskSystems();
|
||||
for (int32 i = count - 1; i >= 0; i--) {
|
||||
if (KDiskSystem *diskSystem = DiskSystemAt(i)) {
|
||||
fDiskSystems.RemoveItem(i);
|
||||
if (diskSystem->IsLoaded()) {
|
||||
DBG(OUT("WARNING: Disk system `%s' (%ld) is still loaded!\n",
|
||||
diskSystem->Name(), diskSystem->ID()));
|
||||
} else
|
||||
delete diskSystem;
|
||||
}
|
||||
for (int32 cookie = 0;
|
||||
KDiskSystem *diskSystem = NextDiskSystem(&cookie); ) {
|
||||
fDiskSystems->Remove(diskSystem->ID());
|
||||
if (diskSystem->IsLoaded()) {
|
||||
DBG(OUT("WARNING: Disk system `%s' (%ld) is still loaded!\n",
|
||||
diskSystem->Name(), diskSystem->ID()));
|
||||
} else
|
||||
delete diskSystem;
|
||||
}
|
||||
|
||||
// delete the containers
|
||||
delete fPartitions;
|
||||
delete fDevices;
|
||||
delete fDiskSystems;
|
||||
delete fObsoletePartitions;
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
status_t
|
||||
KDiskDeviceManager::InitCheck() const
|
||||
{
|
||||
return B_OK;
|
||||
if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions)
|
||||
return B_NO_MEMORY;
|
||||
return (fLock.Sem() >= 0 ? B_OK : fLock.Sem());
|
||||
}
|
||||
|
||||
// CreateDefault
|
||||
@ -158,7 +206,7 @@ KDiskDevice *
|
||||
KDiskDeviceManager::FindDevice(const char *path, bool noShadow)
|
||||
{
|
||||
// TODO: Handle shadows correctly!
|
||||
for (int32 i = 0; KDiskDevice *device = fDevices.ItemAt(i); i++) {
|
||||
for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie); ) {
|
||||
if (device->Path() && !strcmp(path, device->Path()))
|
||||
return device;
|
||||
}
|
||||
@ -181,7 +229,10 @@ KDiskDeviceManager::FindPartition(const char *path, bool noShadow)
|
||||
{
|
||||
// TODO: Handle shadows correctly!
|
||||
// TODO: Optimize!
|
||||
for (int32 i = 0; KPartition *partition = fPartitions.ItemAt(i); i++) {
|
||||
for (PartitionMap::Iterator it = fPartitions->Begin();
|
||||
it != fPartitions->End();
|
||||
++it) {
|
||||
KPartition *partition = it->Value();
|
||||
char partitionPath[B_PATH_NAME_LENGTH];
|
||||
if (partition->GetPath(partitionPath) == B_OK
|
||||
&& !strcmp(path, partitionPath)) {
|
||||
@ -196,10 +247,9 @@ KPartition *
|
||||
KDiskDeviceManager::FindPartition(partition_id id, bool noShadow)
|
||||
{
|
||||
// TODO: Handle shadows correctly!
|
||||
for (int32 i = 0; KPartition *partition = fPartitions.ItemAt(i); i++) {
|
||||
if (partition->ID() == id)
|
||||
return partition;
|
||||
}
|
||||
PartitionMap::Iterator it = fPartitions->Find(id);
|
||||
if (it != fPartitions->End())
|
||||
return it->Value();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -208,7 +258,7 @@ KFileDiskDevice *
|
||||
KDiskDeviceManager::FindFileDevice(const char *filePath, bool noShadow)
|
||||
{
|
||||
// TODO: Handle shadows correctly!
|
||||
for (int32 i = 0; KDiskDevice *device = fDevices.ItemAt(i); i++) {
|
||||
for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie); ) {
|
||||
KFileDiskDevice *fileDevice = dynamic_cast<KFileDiskDevice*>(device);
|
||||
if (fileDevice && fileDevice->FilePath()
|
||||
&& !strcmp(filePath, fileDevice->FilePath())) {
|
||||
@ -253,14 +303,9 @@ KDiskDeviceManager::RegisterNextDevice(int32 *cookie)
|
||||
if (!cookie)
|
||||
return NULL;
|
||||
if (ManagerLocker locker = this) {
|
||||
// TODO: This loop assumes that the device list is ordered. Make sure
|
||||
// that this is really the case.
|
||||
for (int32 i = 0; KDiskDevice *device = fDevices.ItemAt(i); i++) {
|
||||
if (device->ID() >= *cookie) {
|
||||
device->Register();
|
||||
*cookie = device->ID() + 1;
|
||||
return device;
|
||||
}
|
||||
if (KDiskDevice *device = NextDevice(cookie)) {
|
||||
device->Register();
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@ -361,25 +406,29 @@ KDiskDeviceManager::DeleteFileDevice(const char *filePath)
|
||||
int32
|
||||
KDiskDeviceManager::CountDevices()
|
||||
{
|
||||
if (ManagerLocker locker = this)
|
||||
return fDevices.CountItems();
|
||||
return 0;
|
||||
return fDevices->Count();
|
||||
}
|
||||
|
||||
// DiskAt
|
||||
// NextDevice
|
||||
KDiskDevice *
|
||||
KDiskDeviceManager::DeviceAt(int32 index)
|
||||
KDiskDeviceManager::NextDevice(int32 *cookie)
|
||||
{
|
||||
if (ManagerLocker locker = this)
|
||||
return fDevices.ItemAt(index);
|
||||
return 0;
|
||||
if (!cookie)
|
||||
return NULL;
|
||||
DeviceMap::Iterator it = fDevices->FindClose(*cookie, false);
|
||||
if (it != fDevices->End()) {
|
||||
KDiskDevice *device = it->Value();
|
||||
*cookie = device->ID() + 1;
|
||||
return device;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// PartitionAdded
|
||||
bool
|
||||
KDiskDeviceManager::PartitionAdded(KPartition *partition)
|
||||
{
|
||||
return (partition && fPartitions.AddItem(partition));
|
||||
return (partition && fPartitions->Put(partition->ID(), partition) == B_OK);
|
||||
}
|
||||
|
||||
// PartitionRemoved
|
||||
@ -387,10 +436,10 @@ bool
|
||||
KDiskDeviceManager::PartitionRemoved(KPartition *partition)
|
||||
{
|
||||
if (partition && partition->PrepareForRemoval()
|
||||
&& fPartitions.RemoveItem(partition)) {
|
||||
&& fPartitions->Remove(partition->ID())) {
|
||||
// If adding the partition to the obsolete list fails (due to lack
|
||||
// of memory), we can't do anything about it. We will leak memory then.
|
||||
fObsoletePartitions.AddItem(partition);
|
||||
fObsoletePartitions->Insert(partition);
|
||||
partition->MarkObsolete();
|
||||
return true;
|
||||
}
|
||||
@ -404,7 +453,7 @@ KDiskDeviceManager::DeletePartition(KPartition *partition)
|
||||
if (partition && partition->IsObsolete()
|
||||
&& partition->CountReferences() == 0
|
||||
&& partition->PrepareForDeletion()
|
||||
&& fObsoletePartitions.RemoveItem(partition)) {
|
||||
&& fObsoletePartitions->Remove(partition)) {
|
||||
delete partition;
|
||||
return true;
|
||||
}
|
||||
@ -463,7 +512,8 @@ KDiskDeviceManager::JobQueueAt(int32 index)
|
||||
KDiskSystem *
|
||||
KDiskDeviceManager::DiskSystemWithName(const char *name)
|
||||
{
|
||||
for (int32 i = 0; KDiskSystem *diskSystem = fDiskSystems.ItemAt(i); i++) {
|
||||
for (int32 cookie = 0;
|
||||
KDiskSystem *diskSystem = NextDiskSystem(&cookie); ) {
|
||||
if (!strcmp(name, diskSystem->Name()))
|
||||
return diskSystem;
|
||||
}
|
||||
@ -474,10 +524,9 @@ KDiskDeviceManager::DiskSystemWithName(const char *name)
|
||||
KDiskSystem *
|
||||
KDiskDeviceManager::DiskSystemWithID(disk_system_id id)
|
||||
{
|
||||
for (int32 i = 0; KDiskSystem *diskSystem = fDiskSystems.ItemAt(i); i++) {
|
||||
if (diskSystem->ID() == id)
|
||||
return diskSystem;
|
||||
}
|
||||
DiskSystemMap::Iterator it = fDiskSystems->Find(id);
|
||||
if (it != fDiskSystems->End())
|
||||
return it->Value();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -485,14 +534,22 @@ KDiskDeviceManager::DiskSystemWithID(disk_system_id id)
|
||||
int32
|
||||
KDiskDeviceManager::CountDiskSystems()
|
||||
{
|
||||
return fDiskSystems.CountItems();
|
||||
return fDiskSystems->Count();
|
||||
}
|
||||
|
||||
// DiskSystemAt
|
||||
// NextDiskSystem
|
||||
KDiskSystem *
|
||||
KDiskDeviceManager::DiskSystemAt(int32 index)
|
||||
KDiskDeviceManager::NextDiskSystem(int32 *cookie)
|
||||
{
|
||||
return fDiskSystems.ItemAt(index);
|
||||
if (!cookie)
|
||||
return NULL;
|
||||
DiskSystemMap::Iterator it = fDiskSystems->FindClose(*cookie, false);
|
||||
if (it != fDiskSystems->End()) {
|
||||
KDiskSystem *diskSystem = it->Value();
|
||||
*cookie = diskSystem->ID() + 1;
|
||||
return diskSystem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// LoadDiskSystem
|
||||
@ -517,12 +574,10 @@ KDiskDeviceManager::LoadNextDiskSystem(int32 *cookie)
|
||||
if (ManagerLocker locker = this) {
|
||||
// TODO: This loop assumes that the disk system list is ordered.
|
||||
// Make sure that this is really the case.
|
||||
for (int32 i = 0; KDiskSystem *diskSystem = DiskSystemAt(i); i++) {
|
||||
if (diskSystem->ID() >= *cookie) {
|
||||
if (diskSystem->Load() == B_OK) {
|
||||
*cookie = diskSystem->ID() + 1;
|
||||
return diskSystem;
|
||||
}
|
||||
if (KDiskSystem *diskSystem = NextDiskSystem(cookie)) {
|
||||
if (diskSystem->Load() == B_OK) {
|
||||
*cookie = diskSystem->ID() + 1;
|
||||
return diskSystem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -583,8 +638,8 @@ DBG(OUT("KDiskDeviceManager::_AddDiskSystem(%s)\n", diskSystem->Name()));
|
||||
status_t error = diskSystem->Init();
|
||||
if (error != B_OK)
|
||||
DBG(OUT(" initialization failed: %s\n", strerror(error)));
|
||||
if (error == B_OK && !fDiskSystems.AddItem(diskSystem))
|
||||
error = B_NO_MEMORY;
|
||||
if (error == B_OK)
|
||||
error = fDiskSystems->Put(diskSystem->ID(), diskSystem);
|
||||
if (error != B_OK)
|
||||
delete diskSystem;
|
||||
DBG(OUT("KDiskDeviceManager::_AddDiskSystem() done: %s\n", strerror(error)));
|
||||
@ -597,7 +652,7 @@ KDiskDeviceManager::_AddDevice(KDiskDevice *device)
|
||||
{
|
||||
if (!device || !PartitionAdded(device))
|
||||
return false;
|
||||
if (fDevices.AddItem(device))
|
||||
if (fDevices->Put(device->ID(), device) == B_OK)
|
||||
return true;
|
||||
PartitionRemoved(device);
|
||||
return false;
|
||||
@ -607,7 +662,8 @@ KDiskDeviceManager::_AddDevice(KDiskDevice *device)
|
||||
bool
|
||||
KDiskDeviceManager::_RemoveDevice(KDiskDevice *device)
|
||||
{
|
||||
return (device && fDevices.RemoveItem(device) && PartitionRemoved(device));
|
||||
return (device && fDevices->Remove(device->ID())
|
||||
&& PartitionRemoved(device));
|
||||
}
|
||||
|
||||
// _Scan
|
||||
|
@ -562,10 +562,11 @@ KPartition::AddChild(KPartition *partition, int32 index)
|
||||
// add partition
|
||||
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
|
||||
if (ManagerLocker locker = manager) {
|
||||
if (!fChildren.AddItem(partition, index))
|
||||
return B_NO_MEMORY;
|
||||
status_t error = fChildren.Insert(partition, index);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (!manager->PartitionAdded(partition)) {
|
||||
fChildren.RemoveItem(index);
|
||||
fChildren.Erase(index);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
partition->SetIndex(index);
|
||||
@ -609,10 +610,10 @@ KPartition::RemoveChild(int32 index)
|
||||
return false;
|
||||
KDiskDeviceManager *manager = KDiskDeviceManager::Default();
|
||||
if (ManagerLocker locker = manager) {
|
||||
KPartition *partition = fChildren.ItemAt(index);
|
||||
KPartition *partition = fChildren.ElementAt(index);
|
||||
PartitionRegistrar _(partition);
|
||||
if (!partition || !manager->PartitionRemoved(partition)
|
||||
|| !fChildren.RemoveItem(index)) {
|
||||
|| !fChildren.Erase(index)) {
|
||||
return false;
|
||||
}
|
||||
_UpdateChildIndices(index + 1);
|
||||
@ -653,7 +654,8 @@ KPartition::RemoveAllChildren()
|
||||
KPartition *
|
||||
KPartition::ChildAt(int32 index) const
|
||||
{
|
||||
return fChildren.ItemAt(index);
|
||||
return (index >= 0 && index < fChildren.Count()
|
||||
? fChildren.ElementAt(index) : NULL);
|
||||
}
|
||||
|
||||
// CountChildren
|
||||
@ -789,8 +791,8 @@ KPartition::Dump(bool deep, int32 level)
|
||||
void
|
||||
KPartition::_UpdateChildIndices(int32 index)
|
||||
{
|
||||
for (int32 i = index; KPartition *child = fChildren.ItemAt(i); i++)
|
||||
child->SetIndex(index);
|
||||
for (int32 i = index; i < fChildren.Count(); i++)
|
||||
fChildren.ElementAt(i)->SetIndex(i);
|
||||
}
|
||||
|
||||
// _NextID
|
||||
|
@ -1,385 +0,0 @@
|
||||
// List.h
|
||||
//
|
||||
// Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// Except as contained in this notice, the name of a copyright holder shall
|
||||
// not be used in advertising or otherwise to promote the sale, use or other
|
||||
// dealings in this Software without prior written authorization of the
|
||||
// copyright holder.
|
||||
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#include <new.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
template<typename ITEM>
|
||||
class DefaultDefaultItemCreator {
|
||||
public:
|
||||
static inline ITEM GetItem() { return ITEM(0); }
|
||||
};
|
||||
|
||||
/*!
|
||||
\class List
|
||||
\brief A generic list implementation.
|
||||
*/
|
||||
template<typename ITEM,
|
||||
typename DEFAULT_ITEM_SUPPLIER = DefaultDefaultItemCreator<ITEM> >
|
||||
class List {
|
||||
public:
|
||||
typedef ITEM item_t;
|
||||
typedef List list_t;
|
||||
|
||||
private:
|
||||
static item_t sDefaultItem;
|
||||
static const size_t kDefaultChunkSize = 10;
|
||||
static const size_t kMaximalChunkSize = 1024 * 1024;
|
||||
|
||||
public:
|
||||
List(size_t chunkSize = kDefaultChunkSize);
|
||||
~List();
|
||||
|
||||
inline const item_t &GetDefaultItem() const;
|
||||
inline item_t &GetDefaultItem();
|
||||
|
||||
bool AddItem(const item_t &item, int32 index);
|
||||
bool AddItem(const item_t &item);
|
||||
// bool AddList(list_t *list, int32 index);
|
||||
// bool AddList(list_t *list);
|
||||
|
||||
bool RemoveItem(const item_t &item);
|
||||
bool RemoveItem(int32 index);
|
||||
|
||||
bool ReplaceItem(int32 index, const item_t &item);
|
||||
|
||||
bool MoveItem(int32 oldIndex, int32 newIndex);
|
||||
|
||||
void MakeEmpty();
|
||||
|
||||
int32 CountItems() const;
|
||||
bool IsEmpty() const;
|
||||
const item_t &ItemAt(int32 index) const;
|
||||
item_t &ItemAt(int32 index);
|
||||
const item_t *Items() const;
|
||||
int32 IndexOf(const item_t &item) const;
|
||||
bool HasItem(const item_t &item) const;
|
||||
|
||||
// debugging
|
||||
int32 GetCapacity() const { return fCapacity; }
|
||||
|
||||
private:
|
||||
inline static void _MoveItems(item_t* items, int32 offset, int32 count);
|
||||
bool _Resize(size_t count);
|
||||
|
||||
private:
|
||||
size_t fCapacity;
|
||||
size_t fChunkSize;
|
||||
int32 fItemCount;
|
||||
item_t *fItems;
|
||||
};
|
||||
|
||||
// sDefaultItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::sDefaultItem(
|
||||
DEFAULT_ITEM_SUPPLIER::GetItem());
|
||||
|
||||
// constructor
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::List(size_t chunkSize)
|
||||
: fCapacity(0),
|
||||
fChunkSize(chunkSize),
|
||||
fItemCount(0),
|
||||
fItems(NULL)
|
||||
{
|
||||
if (fChunkSize == 0 || fChunkSize > kMaximalChunkSize)
|
||||
fChunkSize = kDefaultChunkSize;
|
||||
_Resize(0);
|
||||
}
|
||||
|
||||
// destructor
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::~List()
|
||||
{
|
||||
MakeEmpty();
|
||||
free(fItems);
|
||||
}
|
||||
|
||||
// GetDefaultItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
inline
|
||||
const List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t &
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::GetDefaultItem() const
|
||||
{
|
||||
return sDefaultItem;
|
||||
}
|
||||
|
||||
// GetDefaultItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
inline
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t &
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::GetDefaultItem()
|
||||
{
|
||||
return sDefaultItem;
|
||||
}
|
||||
|
||||
// _MoveItems
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
inline
|
||||
void
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::_MoveItems(item_t* items, int32 offset, int32 count)
|
||||
{
|
||||
if (count > 0 && offset != 0)
|
||||
memmove(items + offset, items, count * sizeof(item_t));
|
||||
}
|
||||
|
||||
// AddItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::AddItem(const item_t &item, int32 index)
|
||||
{
|
||||
bool result = (index >= 0 && index <= fItemCount
|
||||
&& _Resize(fItemCount + 1));
|
||||
if (result) {
|
||||
_MoveItems(fItems + index, 1, fItemCount - index - 1);
|
||||
new(fItems + index) item_t(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// AddItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::AddItem(const item_t &item)
|
||||
{
|
||||
bool result = true;
|
||||
if ((int32)fCapacity > fItemCount) {
|
||||
new(fItems + fItemCount) item_t(item);
|
||||
fItemCount++;
|
||||
} else {
|
||||
if ((result = _Resize(fItemCount + 1)))
|
||||
new(fItems + (fItemCount - 1)) item_t(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// These don't use the copy constructor!
|
||||
/*
|
||||
// AddList
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::AddList(list_t *list, int32 index)
|
||||
{
|
||||
bool result = (list && index >= 0 && index <= fItemCount);
|
||||
if (result && list->fItemCount > 0) {
|
||||
int32 count = list->fItemCount;
|
||||
result = _Resize(fItemCount + count);
|
||||
if (result) {
|
||||
_MoveItems(fItems + index, count, fItemCount - index - count);
|
||||
memcpy(fItems + index, list->fItems,
|
||||
list->fItemCount * sizeof(item_t));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// AddList
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::AddList(list_t *list)
|
||||
{
|
||||
bool result = (list);
|
||||
if (result && list->fItemCount > 0) {
|
||||
int32 index = fItemCount;
|
||||
int32 count = list->fItemCount;
|
||||
result = _Resize(fItemCount + count);
|
||||
if (result) {
|
||||
memcpy(fItems + index, list->fItems,
|
||||
list->fItemCount * sizeof(item_t));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
// RemoveItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::RemoveItem(const item_t &item)
|
||||
{
|
||||
int32 index = IndexOf(item);
|
||||
bool result = (index >= 0);
|
||||
if (result)
|
||||
RemoveItem(index);
|
||||
return result;
|
||||
}
|
||||
|
||||
// RemoveItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::RemoveItem(int32 index)
|
||||
{
|
||||
if (index >= 0 && index < fItemCount) {
|
||||
fItems[index].~item_t();
|
||||
_MoveItems(fItems + index + 1, -1, fItemCount - index - 1);
|
||||
_Resize(fItemCount - 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ReplaceItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::ReplaceItem(int32 index, const item_t &item)
|
||||
{
|
||||
if (index >= 0 && index < fItemCount) {
|
||||
fItems[index] = item;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// MoveItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::MoveItem(int32 oldIndex, int32 newIndex)
|
||||
{
|
||||
if (oldIndex >= 0 && oldIndex < fItemCount
|
||||
&& newIndex >= 0 && newIndex <= fItemCount) {
|
||||
if (oldIndex < newIndex - 1) {
|
||||
item_t item = fItems[oldIndex];
|
||||
_MoveItems(fItems + oldIndex + 1, -1, newIndex - oldIndex - 1);
|
||||
fItems[newIndex] = item;
|
||||
} else if (oldIndex > newIndex) {
|
||||
item_t item = fItems[oldIndex];
|
||||
_MoveItems(fItems + newIndex, 1, oldIndex - newIndex);
|
||||
fItems[newIndex] = item;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// MakeEmpty
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
void
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::MakeEmpty()
|
||||
{
|
||||
for (int32 i = 0; i < fItemCount; i++)
|
||||
fItems[i].~item_t();
|
||||
_Resize(0);
|
||||
}
|
||||
|
||||
// CountItems
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
int32
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::CountItems() const
|
||||
{
|
||||
return fItemCount;
|
||||
}
|
||||
|
||||
// IsEmpty
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::IsEmpty() const
|
||||
{
|
||||
return (fItemCount == 0);
|
||||
}
|
||||
|
||||
// ItemAt
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
const List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t &
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::ItemAt(int32 index) const
|
||||
{
|
||||
if (index >= 0 && index < fItemCount)
|
||||
return fItems[index];
|
||||
return sDefaultItem;
|
||||
}
|
||||
|
||||
// ItemAt
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t &
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::ItemAt(int32 index)
|
||||
{
|
||||
if (index >= 0 && index < fItemCount)
|
||||
return fItems[index];
|
||||
return sDefaultItem;
|
||||
}
|
||||
|
||||
// Items
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
const List<ITEM, DEFAULT_ITEM_SUPPLIER>::item_t *
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::Items() const
|
||||
{
|
||||
return fItems;
|
||||
}
|
||||
|
||||
// IndexOf
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
int32
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::IndexOf(const item_t &item) const
|
||||
{
|
||||
for (int32 i = 0; i < fItemCount; i++) {
|
||||
if (fItems[i] == item)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// HasItem
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::HasItem(const item_t &item) const
|
||||
{
|
||||
return (IndexOf(item) >= 0);
|
||||
}
|
||||
|
||||
// _Resize
|
||||
template<typename ITEM, typename DEFAULT_ITEM_SUPPLIER>
|
||||
bool
|
||||
List<ITEM, DEFAULT_ITEM_SUPPLIER>::_Resize(size_t count)
|
||||
{
|
||||
bool result = true;
|
||||
// calculate the new capacity
|
||||
int32 newSize = count;
|
||||
if (newSize <= 0)
|
||||
newSize = 1;
|
||||
newSize = ((newSize - 1) / fChunkSize + 1) * fChunkSize;
|
||||
// resize if necessary
|
||||
if ((size_t)newSize != fCapacity) {
|
||||
item_t* newItems
|
||||
= (item_t*)realloc(fItems, newSize * sizeof(item_t));
|
||||
if (newItems) {
|
||||
fItems = newItems;
|
||||
fCapacity = newSize;
|
||||
} else
|
||||
result = false;
|
||||
}
|
||||
if (result)
|
||||
fItemCount = count;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // LIST_H
|
@ -24,7 +24,8 @@ main()
|
||||
if (error != B_OK)
|
||||
printf("creating the file device failed: %s\n", strerror(error));
|
||||
if (manager->Lock()) {
|
||||
for (int32 i = 0; KDiskDevice *device = manager->DeviceAt(i); i++) {
|
||||
for (int32 cookie = 0;
|
||||
KDiskDevice *device = manager->NextDevice(&cookie); ) {
|
||||
device->Dump();
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ SubDir OBOS_TOP src tests kernel core disk_device_manager ;
|
||||
#UsePrivateHeaders $(DOT) ;
|
||||
UsePrivateHeaders shared ;
|
||||
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
||||
UsePrivateHeaders [ FDirName kernel util ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src kernel core disk_device_manager ] ;
|
||||
|
||||
SimpleTest DiskDeviceManagerTest
|
||||
|
Loading…
Reference in New Issue
Block a user