Oolite 1.91.0.7745-260117-205bce7
Loading...
Searching...
No Matches
OOCache.m File Reference
import "OOCache.h"
import "OOStringParsing.h"
Include dependency graph for OOCache.m:

Go to the source code of this file.

Classes

protocol  <OOCacheComparable>
struct  OOCacheImpl
struct  OOCacheNode
category  OOCache(Private)

Macros

#define OOCACHE_PERFORM_INTEGRITY_CHECKS   0
#define CHECK_INTEGRITY(context)

Typedefs

typedef struct OOCacheImpl OOCacheImpl
typedef struct OOCacheNode OOCacheNode

Enumerations

enum  { kCountUnknown = -1U }

Functions

static OOCacheImplCacheAllocate (void)
static void CacheFree (OOCacheImpl *cache)
static BOOL CacheInsert (OOCacheImpl *cache, id key, id value)
static BOOL CacheRemove (OOCacheImpl *cache, id key)
static BOOL CacheRemoveOldest (OOCacheImpl *cache, NSString *logKey)
static id CacheRetrieve (OOCacheImpl *cache, id key)
static unsigned CacheGetCount (OOCacheImpl *cache)
static NSArray * CacheArrayOfContentsByAge (OOCacheImpl *cache)
static NSArray * CacheArrayOfNodesByAge (OOCacheImpl *cache)
static NSString * CacheGetName (OOCacheImpl *cache)
static void CacheSetName (OOCacheImpl *cache, NSString *name)
static OOCacheNodeCacheNodeAllocate (id< OOCacheComparable > key, id value)
static void CacheNodeFree (OOCacheImpl *cache, OOCacheNode *node)
static id CacheNodeGetValue (OOCacheNode *node)
static void CacheNodeSetValue (OOCacheNode *node, id value)
static OOCacheNodeTreeSplay (OOCacheNode **root, id< OOCacheComparable > key)
static OOCacheNodeTreeInsert (OOCacheImpl *cache, id< OOCacheComparable > key, id value)
static void AgeListMakeYoungest (OOCacheImpl *cache, OOCacheNode *node)
static void AgeListRemove (OOCacheImpl *cache, OOCacheNode *node)

Variables

static NSString *const kSerializedEntryKeyKey = @"@"key"
static NSString *const kSerializedEntryKeyValue = @"@"value"

Macro Definition Documentation

◆ CHECK_INTEGRITY

#define CHECK_INTEGRITY ( context)
Value:
do {} while (0)

Definition at line 183 of file OOCache.m.

Referenced by OOCache::dealloc, OOCache::objectForKey:, OOCache::removeObjectForKey:, and OOCache::setObject:forKey:.

◆ OOCACHE_PERFORM_INTEGRITY_CHECKS

#define OOCACHE_PERFORM_INTEGRITY_CHECKS   0

Definition at line 115 of file OOCache.m.

Typedef Documentation

◆ OOCacheImpl

typedef struct OOCacheImpl OOCacheImpl

Definition at line 126 of file OOCache.m.

◆ OOCacheNode

typedef struct OOCacheNode OOCacheNode

Definition at line 127 of file OOCache.m.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
kCountUnknown 

Definition at line 157 of file OOCache.m.

157{ kCountUnknown = -1U };
@ kCountUnknown
Definition OOCache.m:157

Function Documentation

◆ AgeListMakeYoungest()

void AgeListMakeYoungest ( OOCacheImpl * cache,
OOCacheNode * node )
static

Definition at line 905 of file OOCache.m.

906{
907 if (cache == NULL || node == NULL) return;
908
909 AgeListRemove(cache, node);
910 node->older = cache->youngest;
911 if (NULL != cache->youngest) cache->youngest->younger = node;
912 cache->youngest = node;
913 if (cache->oldest == NULL) cache->oldest = node;
914}
static void AgeListRemove(OOCacheImpl *cache, OOCacheNode *node)
Definition OOCache.m:918
OOCacheNode * youngest
Definition OOCache.m:135
OOCacheNode * oldest
Definition OOCache.m:135
OOCacheNode * older
Definition OOCache.m:152
OOCacheNode * younger
Definition OOCache.m:152

References AgeListRemove(), OOCacheNode::older, OOCacheImpl::oldest, OOCacheNode::younger, and OOCacheImpl::youngest.

Referenced by CacheInsert(), and CacheRetrieve().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ AgeListRemove()

void AgeListRemove ( OOCacheImpl * cache,
OOCacheNode * node )
static

Definition at line 918 of file OOCache.m.

919{
920 OOCacheNode *younger = NULL;
921 OOCacheNode *older = NULL;
922
923 if (node == NULL) return;
924
925 younger = node->younger;
926 older = node->older;
927
928 if (cache->youngest == node) cache->youngest = older;
929 if (cache->oldest == node) cache->oldest = younger;
930
931 node->younger = NULL;
932 node->older = NULL;
933
934 if (younger != NULL) younger->older = older;
935 if (older != NULL) older->younger = younger;
936}

References OOCacheNode::older, OOCacheImpl::oldest, OOCacheNode::younger, and OOCacheImpl::youngest.

Referenced by AgeListMakeYoungest(), CacheNodeFree(), and CacheRemove().

Here is the caller graph for this function:

◆ CacheAllocate()

OOCacheImpl * CacheAllocate ( void )
static

Definition at line 446 of file OOCache.m.

447{
448 return calloc(sizeof (OOCacheImpl), 1);
449}

Referenced by OOCache::initWithPList:.

Here is the caller graph for this function:

◆ CacheArrayOfContentsByAge()

NSArray * CacheArrayOfContentsByAge ( OOCacheImpl * cache)
static

Definition at line 534 of file OOCache.m.

535{
536 OOCacheNode *node = NULL;
537 NSMutableArray *result = nil;
538
539 if (cache == NULL || cache->count == 0) return nil;
540
541 result = [NSMutableArray arrayWithCapacity:cache->count];
542
543 for (node = cache->youngest; node != NULL; node = node->older)
544 {
545 [result addObject:node->value];
546 }
547 return result;
548}
return nil
unsigned count
Definition OOCache.m:137

References OOCacheImpl::count, nil, OOCacheNode::older, and OOCacheImpl::youngest.

Referenced by OOCache::objectsByAge.

Here is the caller graph for this function:

◆ CacheArrayOfNodesByAge()

NSArray * CacheArrayOfNodesByAge ( OOCacheImpl * cache)
static

Definition at line 551 of file OOCache.m.

552{
553 OOCacheNode *node = NULL;
554 NSMutableArray *result = nil;
555
556 if (cache == NULL || cache->count == 0) return nil;
557
558 result = [NSMutableArray arrayWithCapacity:cache->count];
559
560 for (node = cache->oldest; node != NULL; node = node->younger)
561 {
562 [result addObject:[NSDictionary dictionaryWithObjectsAndKeys:node->key, kSerializedEntryKeyKey, node->value, kSerializedEntryKeyValue, nil]];
563 }
564 return result;
565}
static NSString *const kSerializedEntryKeyKey
Definition OOCache.m:160
static NSString *const kSerializedEntryKeyValue
Definition OOCache.m:161
id< OOCacheComparable > key
Definition OOCache.m:145

References OOCacheImpl::count, nil, OOCacheImpl::oldest, and OOCacheNode::younger.

Referenced by OOCache::pListRepresentation.

Here is the caller graph for this function:

◆ CacheFree()

void CacheFree ( OOCacheImpl * cache)
static

Definition at line 452 of file OOCache.m.

453{
454 if (cache == NULL) return;
455
456 CacheNodeFree(cache, cache->root);
457 [cache->name autorelease];
458 free(cache);
459}
static void CacheNodeFree(OOCacheImpl *cache, OOCacheNode *node)
Definition OOCache.m:629
OOCacheNode * root
Definition OOCache.m:132
NSString * name
Definition OOCache.m:138

References CacheNodeFree(), and OOCacheImpl::root.

Referenced by OOCache::dealloc.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CacheGetCount()

unsigned CacheGetCount ( OOCacheImpl * cache)
static

Definition at line 581 of file OOCache.m.

582{
583 return cache->count;
584}

References OOCacheImpl::count.

Referenced by OOCache::prune.

Here is the caller graph for this function:

◆ CacheGetName()

NSString * CacheGetName ( OOCacheImpl * cache)
static

Definition at line 568 of file OOCache.m.

569{
570 return cache->name;
571}

References OOCacheImpl::name.

Referenced by OOCache::name, and OOCache::prune.

Here is the caller graph for this function:

◆ CacheInsert()

BOOL CacheInsert ( OOCacheImpl * cache,
id key,
id value )
static

Definition at line 462 of file OOCache.m.

463{
464 OOCacheNode *node = NULL;
465
466 if (cache == NULL || key == nil || value == nil) return NO;
467
468 node = TreeInsert(cache, key, value);
469 if (node != NULL)
470 {
471 AgeListMakeYoungest(cache, node);
472 return YES;
473 }
474 else return NO;
475}
static void AgeListMakeYoungest(OOCacheImpl *cache, OOCacheNode *node)
Definition OOCache.m:905
static OOCacheNode * TreeInsert(OOCacheImpl *cache, id< OOCacheComparable > key, id value)
Definition OOCache.m:771

References AgeListMakeYoungest(), nil, and TreeInsert().

Referenced by OOCache::setObject:forKey:.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CacheNodeAllocate()

OOCacheNode * CacheNodeAllocate ( id< OOCacheComparable > key,
id value )
static

Definition at line 611 of file OOCache.m.

612{
613 OOCacheNode *result = NULL;
614
615 if (key == nil || value == nil) return NULL;
616
617 result = calloc(sizeof *result, 1);
618 if (result != NULL)
619 {
620 result->key = [key copy];
621 result->value = [value retain];
622 }
623
624 return result;
625}

References OOCacheNode::key, nil, and OOCacheNode::value.

Referenced by TreeInsert().

Here is the caller graph for this function:

◆ CacheNodeFree()

void CacheNodeFree ( OOCacheImpl * cache,
OOCacheNode * node )
static

Definition at line 629 of file OOCache.m.

630{
631 id key, value;
632
633 if (node == NULL) return;
634
635 AgeListRemove(cache, node);
636
637 key = node->key;
638 node->key = nil;
639 [key release];
640
641 value = node->value;
642 node->value = nil;
643 [value release];
644
645 CacheNodeFree(cache, node->leftChild);
646 CacheNodeFree(cache, node->rightChild);
647
648 free(node);
649}
OOCacheNode * rightChild
Definition OOCache.m:149
OOCacheNode * leftChild
Definition OOCache.m:149

References AgeListRemove(), CacheNodeFree(), OOCacheNode::key, OOCacheNode::leftChild, nil, OOCacheNode::rightChild, and OOCacheNode::value.

Referenced by CacheFree(), CacheNodeFree(), CacheRemove(), and TreeInsert().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CacheNodeGetValue()

id CacheNodeGetValue ( OOCacheNode * node)
static

Definition at line 653 of file OOCache.m.

654{
655 if (node == NULL) return nil;
656
657 return node->value;
658}

References nil, and OOCacheNode::value.

Referenced by CacheRetrieve().

Here is the caller graph for this function:

◆ CacheNodeSetValue()

void CacheNodeSetValue ( OOCacheNode * node,
id value )
static

Definition at line 662 of file OOCache.m.

663{
664 if (node == NULL) return;
665
666 id tmp = node->value;
667 node->value = [value retain];
668 [tmp release];
669}

References OOCacheNode::value.

Referenced by TreeInsert().

Here is the caller graph for this function:

◆ CacheRemove()

BOOL CacheRemove ( OOCacheImpl * cache,
id key )
static

Definition at line 478 of file OOCache.m.

479{
480 OOCacheNode *node = NULL, *newRoot = NULL;
481
482 node = TreeSplay(&cache->root, key);
483 if (node != NULL)
484 {
485 if (node->leftChild == NULL) newRoot = node->rightChild;
486 else
487 {
488 newRoot = node->leftChild;
489 TreeSplay(&newRoot, key);
490 newRoot->rightChild = node->rightChild;
491 }
492 node->leftChild = NULL;
493 node->rightChild = NULL;
494
495 cache->root = newRoot;
496 --cache->count;
497
498 AgeListRemove(cache, node);
499 CacheNodeFree(cache, node);
500
501 return YES;
502 }
503 else return NO;
504}
static OOCacheNode * TreeSplay(OOCacheNode **root, id< OOCacheComparable > key)
Definition OOCache.m:692

References AgeListRemove(), CacheNodeFree(), OOCacheImpl::count, OOCacheNode::leftChild, OOCacheNode::rightChild, OOCacheImpl::root, and TreeSplay().

Referenced by CacheRemoveOldest(), and OOCache::removeObjectForKey:.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CacheRemoveOldest()

BOOL CacheRemoveOldest ( OOCacheImpl * cache,
NSString * logKey )
static

Definition at line 507 of file OOCache.m.

508{
509 // This could be more efficient, but does it need to be?
510 if (cache == NULL || cache->oldest == NULL) return NO;
511
512 OOLog(logKey, @"Pruning cache \"%@\": removing %@", cache->name, cache->oldest->key);
513 return CacheRemove(cache, cache->oldest->key);
514}
static BOOL CacheRemove(OOCacheImpl *cache, id key)
Definition OOCache.m:478
#define OOLog(class, format,...)
Definition OOLogging.h:88

References CacheRemove(), OOCacheNode::key, OOCacheImpl::name, OOCacheImpl::oldest, and OOLog.

Referenced by OOCache::prune.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CacheRetrieve()

id CacheRetrieve ( OOCacheImpl * cache,
id key )
static

Definition at line 517 of file OOCache.m.

518{
519 OOCacheNode *node = NULL;
520 id result = nil;
521
522 if (cache == NULL || key == NULL) return nil;
523
524 node = TreeSplay(&cache->root, key);
525 if (node != NULL)
526 {
527 result = CacheNodeGetValue(node);
528 AgeListMakeYoungest(cache, node);
529 }
530 return result;
531}
static id CacheNodeGetValue(OOCacheNode *node)
Definition OOCache.m:653

References AgeListMakeYoungest(), CacheNodeGetValue(), nil, OOCacheImpl::root, and TreeSplay().

Referenced by OOCache::objectForKey:.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CacheSetName()

void CacheSetName ( OOCacheImpl * cache,
NSString * name )
static

Definition at line 574 of file OOCache.m.

575{
576 [cache->name autorelease];
577 cache->name = [name copy];
578}

References OOCacheImpl::name.

Referenced by OOCache::setName:.

Here is the caller graph for this function:

◆ TreeInsert()

OOCacheNode * TreeInsert ( OOCacheImpl * cache,
id< OOCacheComparable > key,
id value )
static

Definition at line 771 of file OOCache.m.

772{
773 OOCacheNode *closest = NULL,
774 *node = NULL;
775 NSComparisonResult order;
776
777 if (cache == NULL || key == nil || value == nil) return NULL;
778
779 if (cache->root == NULL)
780 {
781 node = CacheNodeAllocate(key, value);
782 cache->root = node;
783 cache->count = 1;
784 }
785 else
786 {
787 node = TreeSplay(&cache->root, key);
788 if (node != NULL)
789 {
790 // Exact match: key already exists, reuse its node
791 CacheNodeSetValue(node, value);
792 }
793 else
794 {
795 closest = cache->root;
796 node = CacheNodeAllocate(key, value);
797 if (EXPECT_NOT(node == NULL)) return NULL;
798
799 order = [key compare:closest->key];
800
801 if (order == NSOrderedAscending)
802 {
803 // Insert to left
804 node->leftChild = closest->leftChild;
805 node->rightChild = closest;
806 closest->leftChild = NULL;
807 cache->root = node;
808 ++cache->count;
809 }
810 else if (order == NSOrderedDescending)
811 {
812 // Insert to right
813 node->rightChild = closest->rightChild;
814 node->leftChild = closest;
815 closest->rightChild = NULL;
816 cache->root = node;
817 ++cache->count;
818 }
819 else
820 {
821 // Key already exists, which we should have caught above
822 OOLog(@"dataCache.inconsistency", @"%s() internal inconsistency for cache \"%@\", insertion failed.", __PRETTY_FUNCTION__, cache->name);
823 CacheNodeFree(cache, node);
824 return NULL;
825 }
826 }
827 }
828
829 return node;
830}
static void CacheNodeSetValue(OOCacheNode *node, id value)
Definition OOCache.m:662
static OOCacheNode * CacheNodeAllocate(id< OOCacheComparable > key, id value)
Definition OOCache.m:611
#define EXPECT_NOT(x)

References CacheNodeAllocate(), CacheNodeFree(), CacheNodeSetValue(), OOCacheImpl::count, EXPECT_NOT, OOCacheNode::leftChild, OOCacheImpl::name, nil, OOLog, OOCacheNode::rightChild, OOCacheImpl::root, and TreeSplay().

Referenced by CacheInsert().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ TreeSplay()

OOCacheNode * TreeSplay ( OOCacheNode ** root,
id< OOCacheComparable > key )
static

Definition at line 692 of file OOCache.m.

693{
694 NSComparisonResult order;
695 OOCacheNode N = { .leftChild = NULL, .rightChild = NULL };
696 OOCacheNode *node = NULL, *temp = NULL, *l = &N, *r = &N;
697 BOOL exact = NO;
698
699 if (root == NULL || *root == NULL || key == nil) return NULL;
700
701 node = *root;
702
703 for (;;)
704 {
705#ifndef NDEBUG
706 if (node == NULL)
707 {
708 OOLog(@"node.error", @"%@", @"node is NULL");
709 }
710 else if (node->key == NULL)
711 {
712 OOLog(@"node.error", @"%@", @"node->key is NULL");
713 }
714#endif
715 order = [key compare:node->key];
716 if (order == NSOrderedAscending)
717 {
718 // Closest match is in left subtree
719 if (node->leftChild == NULL) break;
720 if ([key compare:node->leftChild->key] == NSOrderedAscending)
721 {
722 // Rotate right
723 temp = node->leftChild;
724 node->leftChild = temp->rightChild;
725 temp->rightChild = node;
726 node = temp;
727 if (node->leftChild == NULL) break;
728 }
729 // Link right
730 r->leftChild = node;
731 r = node;
732 node = node->leftChild;
733 }
734 else if (order == NSOrderedDescending)
735 {
736 // Closest match is in right subtree
737 if (node->rightChild == NULL) break;
738 if ([key compare:node->rightChild->key] == NSOrderedDescending)
739 {
740 // Rotate left
741 temp = node->rightChild;
742 node->rightChild = temp->leftChild;
743 temp->leftChild = node;
744 node = temp;
745 if (node->rightChild == NULL) break;
746 }
747 // Link left
748 l->rightChild = node;
749 l = node;
750 node = node->rightChild;
751 }
752 else
753 {
754 // Found exact match
755 exact = YES;
756 break;
757 }
758 }
759
760 // Assemble
761 l->rightChild = node->leftChild;
762 r->leftChild = node->rightChild;
763 node->leftChild = N.rightChild;
764 node->rightChild = N.leftChild;
765
766 *root = node;
767 return exact ? node : NULL;
768}

References OOCacheNode::key, OOCacheNode::leftChild, nil, OOLog, and OOCacheNode::rightChild.

Referenced by CacheRemove(), CacheRetrieve(), and TreeInsert().

Here is the caller graph for this function:

Variable Documentation

◆ kSerializedEntryKeyKey

NSString* const kSerializedEntryKeyKey = @"@"key"
static

Definition at line 160 of file OOCache.m.

◆ kSerializedEntryKeyValue

NSString* const kSerializedEntryKeyValue = @"@"value"
static

Definition at line 161 of file OOCache.m.