Skip to content

Commit

Permalink
Merge pull request #1845 from sebastianbaginski/bytealloc
Browse files Browse the repository at this point in the history
support for custom allocator in ByteBuffer
  • Loading branch information
marcusnaslund authored Aug 1, 2016
2 parents 8f136c2 + 2518a8a commit a74245e
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 7 deletions.
1 change: 1 addition & 0 deletions base.use
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Description: Base library that complements the built-in SDK.
SourcePath: source/base
Imports: Atomic
Imports: Order
Imports: Allocator
Imports: ByteBuffer
Imports: DateTime
Imports: TimeSpan
Expand Down
36 changes: 36 additions & 0 deletions source/base/Allocator.ooc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* This file is part of magic-sdk, an sdk for the open source programming language magic.
*
* Copyright (C) 2016 magic-lang
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

import Owner

AbstractAllocator: abstract class {
_owner: Owner
free: func ~withCriteria (owner: Owner) {
if (owner == this _owner)
this free()
}
allocate: abstract func (size: SizeT) -> Pointer
deallocate: abstract func (pointer: Pointer)
}

MallocAllocator: class extends AbstractAllocator {
init: func (owner := Owner Receiver) { this _owner = owner }
allocate: override func (size: SizeT) -> Pointer { malloc(size) }
deallocate: override func (pointer: Pointer) { memfree(pointer) }
}

Allocator: abstract class {
_defaultAllocator: static AbstractAllocator = null
mallocAllocator := static MallocAllocator new(Owner Sender)
defaultAllocator: static func -> AbstractAllocator {
This _defaultAllocator ?? mallocAllocator as AbstractAllocator
}
free: static func ~all {
This mallocAllocator free(Owner Sender)
}
}
21 changes: 14 additions & 7 deletions source/base/ByteBuffer.ooc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

use collections
import Allocator
import ReferenceCounter
import Debug

Expand All @@ -15,21 +16,24 @@ ByteBuffer: class {
_size: Int
_referenceCount: ReferenceCounter
_ownsMemory: Bool
_allocator: AbstractAllocator
pointer ::= this _pointer
size ::= this _size
referenceCount ::= this _referenceCount

init: func (=_pointer, =_size, ownsMemory := false) {
init: func (=_pointer, =_size, ownsMemory := false, allocator := Allocator defaultAllocator()) {
this _referenceCount = ReferenceCounter new(this)
this _ownsMemory = ownsMemory
this _allocator = allocator
}
free: override func {
if (this _referenceCount != null)
this _referenceCount free()
this _referenceCount = null
if (this _ownsMemory)
memfree(this _pointer)
this _allocator deallocate(this _pointer)
this _pointer = null
this _allocator free(Owner Receiver)
super()
}
zero: func ~whole { this memset(0) }
Expand All @@ -50,14 +54,17 @@ ByteBuffer: class {
copyTo: func (other: This, start: Int, destination: Int, length: Int) {
memcpy(other pointer + destination, this pointer + start, length)
}
new: static func ~size (size: Int) -> This { _RecyclableByteBuffer new(size) }
new: static func ~size (size: Int, allocator := Allocator defaultAllocator()) -> This { _RecyclableByteBuffer new(size, allocator) }
new: static func ~recover (pointer: Byte*, size: Int, recover: Func (This) -> Bool) -> This {
_RecoverableByteBuffer new(pointer, size, recover)
}
free: static func ~all { _RecyclableByteBuffer _free~all() }
free: static func ~all {
_RecyclableByteBuffer _free~all()
}
}

GlobalCleanup register(|| ByteBuffer free~all(), true)
GlobalCleanup register(|| Allocator free~all(), true)

_SlicedByteBuffer: class extends ByteBuffer {
_parent: ByteBuffer
Expand Down Expand Up @@ -86,7 +93,7 @@ _RecoverableByteBuffer: class extends ByteBuffer {
}

_RecyclableByteBuffer: class extends ByteBuffer {
init: func (pointer: Byte*, size: Int) { super(pointer, size, true) }
init: func (pointer: Byte*, size: Int, allocator := Allocator defaultAllocator()) { super(pointer, size, true, allocator) }
_forceFree: func {
this _size = 0
this free()
Expand All @@ -111,7 +118,7 @@ _RecyclableByteBuffer: class extends ByteBuffer {
_smallRecycleBin := static VectorList<This> new()
_mediumRecycleBin := static VectorList<This> new()
_largeRecycleBin := static VectorList<This> new()
new: static func ~fromSize (size: Int) -> This {
new: static func ~fromSize (size: Int, allocator := Allocator defaultAllocator()) -> This {
buffer: This = null
bin := This _getBin(size)
This _lock lock()
Expand All @@ -123,7 +130,7 @@ _RecyclableByteBuffer: class extends ByteBuffer {
}
This _lock unlock()
version(debugByteBuffer) { if (buffer == null) Debug print("No RecyclableByteBuffer available in the bin; allocating a new one") }
buffer == null ? This new(malloc(size), size) : buffer
buffer == null ? This new(allocator allocate(size) as Byte*, size, allocator) : buffer
}
_getBin: static func (size: Int) -> VectorList<This> {
size < 10000 ? This _smallRecycleBin : (size < 100000 ? This _mediumRecycleBin : This _largeRecycleBin)
Expand Down
23 changes: 23 additions & 0 deletions test/base/ByteBufferTest.ooc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@
use base
use unit

CustomAllocator: class extends AbstractAllocator {
_allocCount := 0
_freeCount := static 0
init: func
allocate: override func (size: SizeT) -> Pointer {
this _allocCount += 1
malloc(size)
}
deallocate: override func (pointer: Pointer) {
This _freeCount += 1
memfree(pointer)
}
}

ByteBufferTest: class extends Fixture {
init: func {
super("ByteBuffer")
Expand Down Expand Up @@ -78,6 +92,15 @@ ByteBufferTest: class extends Fixture {
expect(buffer pointer[63] as Int, is equal to(63))
buffer referenceCount decrease()
})
this add("custom alloc", This _testCustomAlloc)
}
_testCustomAlloc: static func {
allocator := CustomAllocator new()
expect(allocator _allocCount, is equal to(0))
buffer := ByteBuffer new(128, allocator)
expect(allocator _allocCount, is equal to(1))
(buffer as _RecyclableByteBuffer) _forceFree()
expect(CustomAllocator _freeCount, is equal to(1))
}
}

Expand Down

0 comments on commit a74245e

Please sign in to comment.