What is the meaning of `copyOnWriteContext` in module `github.com/google/btree`? - b-tree

Recently, I read the source code of google/btree. But I'am conflused by the struct copyOnWriteContext. It is used in node function mutableFor, like following
func (n *node) mutableFor(cow *copyOnWriteContext) *node {
if n.cow == cow {
return n
}
fmt.Println("new node?")
out := cow.newNode()
if cap(out.items) >= len(n.items) {
out.items = out.items[:len(n.items)]
} else {
out.items = make(items, len(n.items), cap(n.items))
}
copy(out.items, n.items)
// Copy children
if cap(out.children) >= len(n.children) {
out.children = out.children[:len(n.children)]
} else {
out.children = make(children, len(n.children), cap(n.children))
}
copy(out.children, n.children)
return out
}
I review all the code in this module, and found that there is only one place create the copyOnWriteContext's instance. It is when the tree is created.
func New(degree int) *BTree {
return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize))
}
So what is the meaning for mutableFor. Because there is only one copyOnWriteContext in the entire code. The n.cow always equals param cow.

n.cow can be nil.
// freeNode frees a node within a given COW context, if it's owned by that
// context. It returns what happened to the node (see freeType const
// documentation).
func (c *copyOnWriteContext) freeNode(n *node) freeType {
if n.cow == c {
// clear to allow GC
n.items.truncate(0)
n.children.truncate(0)
n.cow = nil
if c.freelist.freeNode(n) {
return ftStored
} else {
return ftFreelistFull
}
} else {
return ftNotOwned
}
}

Related

Updating a struct with reflect

I want to make my code shorter and I'm trying to understand how reflect works. The code below works (the real code has many more structs and are much longer). So shortly the function processInput gets string data from a TCP connection and it is used to populate the Hyperdeck struct.
type configuration struct {
videoInput string `cmd:"video input:"`
audioMapping int64 `cmd:"audio mapping:"`
genlockInputResync bool `cmd:"genlock input resync:"`
}
type Hyperdeck struct {
configuration configuration
}
func (hd *Hyperdeck) processInput(s string) {
switch hd.multilineCmd {
case "configuration":
if s != "\r\n" {
if strings.HasPrefix(s, "video input:") {
hd.configuration.videoInput = strings.TrimSpace(s[strings.Index(s, ":")+1 : len(s)-1])
} else if strings.HasPrefix(s, "audio mapping:") {
hd.configuration.audioMapping = stringToInt(strings.TrimSpace(s[strings.Index(s, ":")+1:len(s)-1]), hd)
} else if strings.HasPrefix(s, "genlock input resync:") {
hd.configuration.genlockInputResync = stringToBool(strings.TrimSpace(s[strings.Index(s, ":")+1:len(s)-1]), hd)
}
} else {
hd.multilineCmd = ""
}
}
switch {
case strings.Contains(strings.ToLower(s), "configuration"):
hd.multilineCmd = "configuration"
}
}
I was thinking of making something like this that loops the stuct and identifies the type but I can't figure out how to update the struct. I've read and tried things from multiple websites but I just can't get it right.
func (hd *Hyperdeck) processInput(s string) {
switch hd.multilineCmd {
case "configuration":
if s != "\r\n" {
v := reflect.ValueOf(hd.configuration)
t := v.Type()
for i := 0; i < v.NumField(); i++ {
if strings.HasPrefix(s, t.Field(i).Tag.Get("cmd")) {
if t.Field(i).Type.String() == "string" {
// UPDATE hd.configuration.videoInput
} else if t.Field(i).Type.String() == "int" {
//UPDATE hd.configuration.audioMapping
} else if t.Field(i).Type.String() == "bool" {
//UPDATE hd.configuration.genlockInputResync
}
}
}
} else {
hd.multilineCmd = ""
}
}
switch {
case strings.Contains(strings.ToLower(s), "configuration"):
hd.multilineCmd = "configuration"
}
}
I think this code is usable for strings but can't figure out how to address it...
...FieldByName(types.Field(i).Name).SetString(strings.TrimSpace(s[strings.Index(s, ":")+1 : len(s)-1]))
And maybe the most important question, should I do it with reflect or leave it as it is now?

Argument passed to call that takes no arguments.. Firebase

Not sure why i'm getting this.. any suggestions would be grateful!
I ran into issues with my original coding where I had Firebase pod and Firebase Package.. so I started from scratch since that wasnt fixing itself.. now I get this.. and I am at a loss for how to resolve it.
static func fetchUsers() -> AnyPublisher<[UserProfile], Error> {
Future< [UserProfile], Error > { promise in
self.db.collection("Users")
.getDocuments { (snapshot, error) in
if let error = error {
promise(.failure(error))
return
}
guard let snapshot = snapshot else {
promise(.failure(FirebaseError.badSnapshot))
return
}
var users = [UserProfile]()
snapshot.documents.forEach { document in
print(users.count)
if let user = try? document.data(as: UserProfile.self){
if users.contains(where: { $0.id == user.id}) {return}
users.append(user)
} else {
print("Not working")
}
}
promise(.success(users))
}
}
.eraseToAnyPublisher()
}
I believe this is the syntax you're after:
var users = [UserProfile]()
users = snapshot.documents.compactMap { (document) -> UserProfile? in
if users.contains(where: { $0.id == user.id}) {
return nil
} else {
return try? document.data(as: UserProfile.self)
}
}
Also be aware that when you iterate something in Swift and encounter a false condition on an iteration, return will return out of the greater scope, not just that iteration. Therefore, use continue.
for x in y {
guard x > 0 else {
continue // continues loop
}
// ...
}

Swift 3: how to write this for(;;) loop

Looks like Apple doesn't like C loops, but doesn't provide good approach over it (or I couldn't find it). I have such loop to go from some view to the root in UI hierarchy:
for var parentView = view; parentView != nil; parentView = parentView.parent {
...
}
How to write this in Swift 3 manner?
This would be a way to do it in Swift 3:
var parentView: View! = view
while parentView != nil {
// Do stuff
parentView = parentView.parent
}
If you want to group the loop progression stuff next to while and not at the end of block, you may use defer, like this:
var parentView: View! = view
while parentView != nil {
defer { parentView = parentView.parent }
// Do stuff
}
If you want to limit the scope of parentView, you can encapsulate everything in a do block:
do {
var parentView: View! = view
while parentView != nil {
defer { parentView = parentView.parent }
// Do stuff
}
}
But it's quite verbose so you could define a new generic function for similar loops, like this:
func kindaCStyleLoop<T>(first: T, obtainNext: T -> T?, action: T -> ()) {
var current: T! = first
repeat {
action(current)
current = obtainNext(current)
} while current != nil
}
kindaCStyleLoop(view, obtainNext: { $0.parent }) {
// Do stuff with $0
}
And a last one that relies on GeneratorType and SequenceType to enable using the for-in-loop syntax:
struct CStyleGenerator<T> : GeneratorType, SequenceType {
let getNext: T -> T?
var current: T!
init(first: T, getNext: T -> T?) {
self.getNext = getNext
self.current = first
}
mutating func next() -> T? {
defer {
if current != nil {
current = getNext(current)
}
}
return current
}
}
for parentView in CStyleGenerator(first: view, getNext: { $0.parent }) {
// Do stuff with parentView
}
Correct but too-late answer: there are built-in functions in Swift 3 which provide the solution:
public func sequence<T>(first: T, next: (T) -> T?) -> UnfoldSequence<T, (T?, Bool)>
public func sequence<T, State>(state: State, next: (inout State) -> T?) -> UnfoldSequence<T, State>
We can use them in this manner:
sequence(first: view, next: {
// do something with $0...
return $0.superview
})
For instance
for view in views where view.superview != nil {
}

How do I write a generic recursive function that takes a CollectionType in Swift?

How would you create a generic function to process a CollectionType in Swift? For example, I want something that boils down to this:
func f<C: CollectionType>(list: C) {
if list.isEmpty {
return
}
else {
f(list.dropFirst()) // causes error
}
}
This causes an error because SubSequence might not be a CollectionType: Cannot invoke 'f' with an argument list of type '(C.SubSequence)'
I tried working around it by constraining the SubSequence type like this:
<C: CollectionType where C.SubSequence: CollectionType>
I get the same error, though. Any suggestions on how to write a generic recursive function for CollectionType?
To fix your error, you can transform a SubSequence into an array with the Array initializer:
func f<C: CollectionType>(list: C) {
if list.isEmpty {
return
}
else {
f(Array(list.dropFirst()))
}
}
Here's a solution that doesn't require copying the storage in a new array with every iteration:
func f<C: CollectionType
where C.SubSequence: CollectionType,
C.SubSequence == C.SubSequence.SubSequence>(c: C) {
guard let first = c.first else { return }
print(first)
f(c.dropFirst())
}
In Swift 3:
func f<C>(_ c: C) where
C: Collection,
C.SubSequence: Collection,
C.SubSequence == C.SubSequence.SubSequence {
guard !c.isEmpty else { return }
f(c.dropFirst())
}
f([1, 2, 3])

Swift: filter protocol array by comparing types

(first post)
usually im able to find answers here or elsewhere but no luck this time =(
Question: in Swift, how do you filter an array that is of a protocol type by an implementing type supplied as a function parameter?
protocol Aprotocol {
var number:Int { get set }
}
class Aclass: Aprotocol {
var number = 1
}
class AnotherClass: Aprotocol {
var number = 1
}
var array:[Aprotocol] = [ Aclass(), AnotherClass(), Aclass() ]
func foo (parameter:Aprotocol) -> Int {
return array.filter({ /* p in p.self == parameter.self */ }).count
}
var bar:Aprotocol = // Aclass() or AnotherClass()
var result:Int = foo(bar) // should return 2 or 1, depending on bar type
maybe this is not the right approach at all?
thanks!
Here is what I think you want:
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == parameter.dynamicType
}.count
But I recommend this, which does the same, but without the useless instance of Aclass() which is passed in the answer on the top. Also this way is faster:
func foo <T: Aprotocol>(type: T.Type) -> Int {
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == type
}.count
}
var result:Int = foo(Aclass)
The dynamicType will return the Type of an instance
Very easy:
return array.filter({ parameter.number == $0.number }).count
Kametrixoms solution works (if you use "is T" instead of "== type") but in my case, since i didnt know which implementing class was going to call it, had to go with this solution:
protocol Aprotocol: AnyObject {
var number:Int { get set }
}
class func foo(parameter: AnyObject) -> Int {
return array.filter ({ (element: Aprotocol) -> Bool in
object_getClassName(element) == object_getClassName(parameter)
}).count
}

Resources