pthread_create swift sample
Faced the problem too. Here is short sample below. Hope it help someone further:
Swift 4
class ThreadContext {
var someValue: String = "Some value"
}
func doSomething(pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
let pContext = pointer.bindMemory(to: ThreadContext.self, capacity: 1)
print("Hello world: \(pContext.pointee.someValue)")
return nil
}
var attibutes = UnsafeMutablePointer<pthread_attr_t>.allocate(capacity: 1)
guard 0 == pthread_attr_init(attibutes) else {
fatalError("unable to initialize attributes")
}
defer {
pthread_attr_destroy(attibutes)
}
guard 0 == pthread_attr_setdetachstate(attibutes, PTHREAD_CREATE_JOINABLE) else {
fatalError("unable to set detach state")
}
let pContext = UnsafeMutablePointer<ThreadContext>.allocate(capacity: 1)
var context = ThreadContext()
pContext.pointee = context
var thread: pthread_t? = nil
let result = pthread_create(&thread, attibutes, doSomething, pContext)
guard result == 0, let thread = thread else {
fatalError("unable to start pthread")
}
pthread_join(thread, nil)
Spawn thread with Swift entry point from within C function in iOS
You can access POSIX threading mechanisms in Swift. I have some examples of working with C in this project and this other hobby project. Hopefully they are useful to you.
When working with things like pthread_create
you will want to pass in either a Swift function or closure as the function pointer argument. I attempted going from Swift => C and having C start the thread with a Swift function via @_cdecl
and wasn't able to get it working. It might be possible but the context of how I had things setup I couldn't get it in this case.
The other thing to keep in mind is that once you are in C land you will need a way to get back. This is typically done through void*
as your context pointer. From Swift you will likely want to pass in an UnsafePointer
you are managing or use Unmanaged<T>
to directly pass a class instance you have into C and back into Swift.
POSIX threading on ios
One potential issue would be how the storage for the passed in structure mystruct
is created. The lifetime of that variable is very critical to its usage in the thread. For example, if the caller of detachnewthread
had that declared on the stack and then returned before the thread finished, it would be undefined behavior. Likewise, if it were dynamically allocated, then it is necessary to make sure it is not freed before the thread is finished.
In response to the comment/question: The necessity of some kind of mutex depends on the usage. For the sake of discussion, I will assume it is dynamically allocated. If the calling thread fills in the contents of the structure prior to creating the "child" thread and can guarantee that it will not be freed until after the child thread exits, and the subsequent access is read/only, then you would not need a mutex to protect it. I can imagine that type of scenario if the structure contains information that the child thread needs for completing its task.
If, however, more than one thread will be accessing the contents of the structure and one or more threads will be changing the data (writing to the structure), then you probably do need a mutex to protect it.
Who creates and owns the call stack and how does call stack works in multithread?
XNU kernel does it. Swift threads are POSIX pthreads aka Mach threads. During program startup the XNU kernel parses Mach-O executable format and handles either modern LC_MAIN
or legacy LC_UNIXTHREAD
load command (among others). This is handled in kernel functions:
static
load_return_t
load_main(
struct entry_point_command *epc,
thread_t thread,
int64_t slide,
load_result_t *result
)
&
static
load_return_t
load_unixthread(
struct thread_command *tcp,
thread_t thread,
int64_t slide,
load_result_t *result
)
which do happen to be open source
LC_MAIN
initialises the stack through thread_userstackdefault
LC_UNIXTHREAD
through load_threadstack
.
As @PeterCordes mentions in comments only when the kernel creates the main thread the started process itself can spawn child threads from it's own main thread either through some api like GCD or directly through syscall (bsdthread_create
, not sure if any others). The syscall happens to haveuser_addr_t stack
as it's 3rd argument (i.e. rdx
in x86-64 System V kernel ABI used by MacOS). Reference for MacOS syscalls
I haven't thoroughly investigated details of this particular stack argument, but I would imagine it's similar to thread_userstackdefault
/ load_threadstack
approach.
I do believe your doubt about Swift runtime responsibility may arise due to frequent mentions of data structures (like Swift struct
- no pun intended) being stored on the stack (which is btw implementation detail and not guaranteed feature of the runtime).
Update:
He's an example main.swift
command line program ilustrating the idea.
import Foundation
struct testStruct {
var a: Int
}
class testClass {
}
func testLocalVariables() {
print("main thread function with local varablies")
var struct1 = testStruct(a: 5)
withUnsafeBytes(of: &struct1) { print($0) }
var classInstance = testClass()
print(NSString(format: "%p", unsafeBitCast(classInstance, to: Int.self)))
}
testLocalVariables()
print("Main thread", Thread.isMainThread)
var struct1 = testStruct(a: 5)
var struct1Copy = struct1
withUnsafeBytes(of: &struct1) { print($0) }
withUnsafeBytes(of: &struct1Copy) { print($0) }
var string = "testString"
var stringCopy = string
withUnsafeBytes(of: &string) { print($0) }
withUnsafeBytes(of: &stringCopy) { print($0) }
var classInstance = testClass()
var classInstanceAssignment = classInstance
var classInstance2 = testClass()
print(NSString(format: "%p", unsafeBitCast(classInstance, to: Int.self)))
print(NSString(format: "%p", unsafeBitCast(classInstanceAssignment, to: Int.self)))
print(NSString(format: "%p", unsafeBitCast(classInstance2, to: Int.self)))
DispatchQueue.global(qos: .background).async {
print("Child thread", Thread.isMainThread)
withUnsafeBytes(of: &struct1) { print($0) }
withUnsafeBytes(of: &struct1Copy) { print($0) }
withUnsafeBytes(of: &string) { print($0) }
withUnsafeBytes(of: &stringCopy) { print($0) }
print(NSString(format: "%p", unsafeBitCast(classInstance, to: Int.self)))
print(NSString(format: "%p", unsafeBitCast(classInstanceAssignment, to: Int.self)))
print(NSString(format: "%p", unsafeBitCast(classInstance2, to: Int.self)))
}
//Keep main thread alive indefinitely so that process doesn't exit
CFRunLoopRun()
My output looks like this:
main thread function with local varablies
UnsafeRawBufferPointer(start: 0x00007ffeefbfeff8, count: 8)
0x7fcd0940cd30
Main thread true
UnsafeRawBufferPointer(start: 0x000000010058a6f0, count: 8)
UnsafeRawBufferPointer(start: 0x000000010058a6f8, count: 8)
UnsafeRawBufferPointer(start: 0x000000010058a700, count: 16)
UnsafeRawBufferPointer(start: 0x000000010058a710, count: 16)
0x7fcd0940cd40
0x7fcd0940cd40
0x7fcd0940c900
Child thread false
UnsafeRawBufferPointer(start: 0x000000010058a6f0, count: 8)
UnsafeRawBufferPointer(start: 0x000000010058a6f8, count: 8)
UnsafeRawBufferPointer(start: 0x000000010058a700, count: 16)
UnsafeRawBufferPointer(start: 0x000000010058a710, count: 16)
0x7fcd0940cd40
0x7fcd0940cd40
0x7fcd0940c900
Now we can observe a couple of interesting things:
Class
instances clearly occupy a different part of memory thanStructs
- Assigning a struct to a new variable makes a copy to a new memory address
- Assigning class instance just copies the pointer.
- Both main thread and child thread when referring to global
Structs
point to exactly same memory - Strings do have a Struct container.
Update2 - proof of 4^
We can actually inspect the memory underneath:
x 0x10058a6f0 -c 8
0x10058a6f0: 05 00 00 00 00 00 00 00 ........
x 0x10058a6f8 -c 8
0x10058a6f8: 05 00 00 00 00 00 00 00 ........
So this definitely is the actual struct raw data i.e. the struct itself.
Update 3
I added a testLocalVariables()
function, to distinguish between Swift Struct
defined as global and local variables. In this case
x 0x00007ffeefbfeff8 -c 8
0x7ffeefbfeff8: 05 00 00 00 00 00 00 00 ........
it clearly lives on the thread stack.
Last but not least when in lldb
I do:
re read rsp
rsp = 0x00007ffeefbfefc0 from main thread
re read rsp
rsp = 0x000070000291ea40 from child thread
it yields different value for each thread, so the thread stacks are clearly distinct.
Digging further
There's a handy memory region lldb command which sheds some light what's going on.
memory region 0x000000010058a6f0
[0x000000010053d000-0x000000010058b000) rw- __DATA
So global Structs
sit in preallocated executable writeable __DATA
memory page (same one where your global variables live). Same command for class 0x7fcd0940cd40
address isn't as spectacular (I reckon because that's a dynamically allocated heap). Analogously for thread stack address 0x7ffeefbfefc0
which clearly isn't a process memory region.
Fortunately there is one last tool to further go down the rabbit hole.
vmmap -v -purge pid which does confirm classes sit in MALLOC_
ed heap and likewise a thread stack (at least for main thread) can be cross referenced to Stack
.
Somewhat related question is also here.
HTH
How to get thread id of a pthread in linux c program?
pthread_self()
function will give the thread id of current thread.
pthread_t pthread_self(void);
The pthread_self()
function returns the Pthread handle of the calling thread. The pthread_self() function does NOT return the integral thread of the calling thread. You must use pthread_getthreadid_np()
to return an integral identifier for the thread.
NOTE:
pthread_id_np_t tid;
tid = pthread_getthreadid_np();
is significantly faster than these calls, but provides the same behavior.
pthread_id_np_t tid;
pthread_t self;
self = pthread_self();
pthread_getunique_np(&self, &tid);
Using NSJSONSerialization with swift on ubuntu/linux
NSJSONSerialization is partly implemented (serialization is not yet implemented)
do it yourself, in accordance with your needs, and you will see, that it is the best investment and great way to understand Swift and its possibilities. you can also use one of the opensource libraries available around. SwiftyJSON is very popular, for an example
As mentioned by Sebastian Osiński, unfortunately it use NSJSONSerialization too.
you can check this very simple, but working example swift json. it is far away to be 'perfect', but as an inspiration it could help you, i hope so.
Related Topics
Ios8 Swift Uisearchcontroller Hides Navigationbar
Uitableviewautomaticdimension Not Working on iOS 8
Pattern Variable Binding Cannot Appear in an Expression
How to Properly Calculate 1 Second with Deltatime in Swift
How to Make Function That Some Parameters Not Required in When Call It in iOS Swift 3
Why Are Uiscreen.Bounds Incorrect in iOS11
Argument of '#Selector' Does Not Refer to an '@Objc' Method, Property or Initializer
How to Get Frame Data in Apprtc iOS App for Video Modifications
Swift: Specialize Method of Generic Class for Function Types
Change the Font of a Datepicker
How to Print Escape Sequence Characters in Swift
Checking Conforms Protocol with Associatedtype in Swift
Make a Grid of Buttons of Same Width and Height in Swiftui
Formula to Pick Every Pixel in a Bitmap Without Repeating
How to Get the Url from Webview in Swift
How to Read File Data Applications Document Directory in Swift
Provide Simple Method to Get Current Speed (Implementing Speedometer)