5. We held a workshop at the conference
• React Web App with Kotlin on
Server & Browser
About Instil
6. Excellent interoperability
• Call legacy Java code easily
• Make calls into Kotlin from Java
Really clear, yet concise syntax
• Reduces your codebase by 1/3+
Beloved by frameworks
• First class language on Android
• Mainstream language for Spring via
the Spring Initializr and Spring Fu
• New language for the Gradle DSL
• Kotlin specific frameworks emerging
• Notably Arrow and Ktor
Why Kotlin? Null Safety
String Templates
Default parameters
Extensions
Free Functions
Coroutines
Single Expression
Functions
Reified generics
Data classes and
Properties
Type Inference
Smart Casts
Operator
overloading
8. Java is a legacy language!
But in Java 11…
Kotlin has it today!!
Scala had it
years ago!!
No one gives
a **** about
modules!!
9. Kotlin was originally for the desktop and server
• As JetBrains own internal language
Then it exploded amongst the Android community
• This is still where it is most commonly found
Now its going further
• Kotlin Native builds apps to run outside the VM
• Kotlin JS is transpiled to run inside the browser
Kotlin On Other Platforms
10. Let the buyer beware!
• Everything you see is the
result of my own hacking
• I am very much still in the
learning stages myself…
A Warning…
12. Kotlin Native compiles Kotlin code to native binaries
• It produces executables that run without a virtual machine
The binary output is not portable, but the source is
• The compiler can compile the same source to multiple outputs
• The source can be placed into a multiplatform project
Introducing Kotlin Native
Kotlin Native
Compiler
LLVM Source LLVM
IR
Native
Binary
13. Supported platforms include,
• iOS (arm32, arm64, emulator x86_64)
• MacOS (x86_64)
• Android (arm32, arm64)
• Windows (mingw x86_64)
• Linux (x86_64, arm32, MIPS, MIPS little endian)
• WebAssembly (wasm32)
There is interop with C, Objective-C and Swift
• Kotlin code can call into any of these and vice versa
• Tools like ‘cinterop’ generate Kotlin declarations
based on C declarations found in header files
Introducing Kotlin Native
14. Common things such as Kotlin.io aren’t available
You can use POSIX and interop to achieve functionality or
use other multiplatform libraries
Introducing Kotlin Native
import kotlinx.cinterop.*
import platform.posix.*
import kotlinx.io.*
17. From the main thread we wish to start two Pthreads
• With the names ‘Thread No1’ and ‘Thread No2’
• This can be accomplished via ‘pthread_create’
Each thread will print out twenty messages
• In turn each message will be divided into three parts
We want the parts of each message to be atomic
• We do this by creating a mutex and passing it to the threads
• Each thread will:
• Acquire the mutex via ‘pthread_mutex_lock’
• Print the three parts of the message and releases it
• Release the mutex via ‘pthread_mutex_unlock’
The main thread will waits for the Pthreads
• This can be accomplished via ‘pthread_join’
A Demo of Pthreads
18. A Demo of Pthreads
Pthread Thread No1 message 1 part A
Pthread Thread No1 message 1 part B
Pthread Thread No1 message 1 part C
Pthread Thread No2 message 1 part A
Pthread Thread No2 message 1 part B
Pthread Thread No2 message 1 part C
Pthread Thread No1 message 2 part A
Pthread Thread No1 message 2 part B
Pthread Thread No1 message 2 part C
Pthread Thread No2 message 2 part A
Pthread Thread No2 message 2 part B
Pthread Thread No2 message 2 part C
Pthread Thread No1 message 3 part A
Pthread Thread No1 message 3 part B
Pthread Thread No1 message 3 part C
Pthread Thread No2 message 3 part A
Pthread Thread No2 message 3 part B
Pthread Thread No2 message 3 part C
...
...
…
Thread 1 holding mutex
Thread 2 holding mutex
Thread 1 holding mutex
Thread 2 holding mutex
Thread 1 holding mutex
Thread 2 holding mutex
29. Comparing Signatures for ‘pthread_create’
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void*),
void *arg);
public fun pthread_create(
arg0: CValuesRef<pthread_tVar>?,
arg1: CValuesRef<pthread_attr_t>?,
arg2: Cpointer<CFunction<(COpaquePointer?) -> COpaquePointer? >>?,
arg3: CValuesRef<*>?
): kotlin.Int
30. Comparing Signatures for ‘pthread_join’
int pthread_join(pthread_t thread,
void **retval);
public fun pthread_join(
arg0: pthread_t?,
arg1: CValuesRef<COpaquePointerVar>?
): kotlin.Int
31. Comparing Signatures for Mutex functions
int pthread_mutex_init(
pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr
);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
public fun pthread_mutex_init(
arg0: CValuesRef<pthread_mutex_t >?,
arg1: CValuesRef<pthread_mutexattr_t >?
): kotlin.Int
public fun pthread_mutex_destroy(
arg0: CValuesRef<pthread_mutex_t>?
): kotlin.Int
32. The ‘cinterop’ tool generates Kotlin types from C types
• For structures the Kotlin name is the same as the C name
• For other types (e.g. opaque types) it is ‘${type}Var’
A void pointer is represented by the ‘COpaquePointer’ type
• An in-memory instance is represented by ‘COpaquePointerVar’
Pointers are represented in two ways:
• For variables use ‘CPointer<T>’ and ‘CPointerVar<T>’
• For parameters use ‘CValuesRef<T>’
What Have We Learned
34. Memory is allocated via ‘alloc’ functions
• There are versions for single types, arrays, pointers etc…
The memory allocated must be freed
• This can be managed for you via ‘memScoped { … }’
Null in Kotlin is translated into NULL in C
• I.e. the address denoted by zero where nothing lives
• NB Pthreads uses NULL to mean ‘go with the defaults’
Explaining the Demo Code
val mutex = alloc<pthread_mutex_t>()
pthread_mutex_init(mutex.ptr,null)
val threadHandle1 = alloc<pthread_tVar>()
val threadHandle2 = alloc<pthread_tVar>()
35. Kotlin strings are interoperable with C Strings
• The compiler converts between Strings and ‘const char *’
Manual conversion methods are available
• Calling ‘cstr’ on a String returns ‘CValuesRef<ByteVar>’
• You can call ‘toKString’ on a ‘CPointer<ByteVar>’
The ‘StableRef’ type is used to pass values through C
• This typically happens when you are writing a function in Kotlin
which will be called at a later date from C with cached data
• The Pthreads library is a good example of where this is useful
Explaining the Demo Code
val data1 = StableRef.create("Thread No1".cstr.ptr to mutex)
val data2 = StableRef.create("Thread No2".cstr.ptr to mutex)
36. When working with generated types
• Use ‘ptr’ to get the address in memory of a value
• Use ‘value’ to get the value from an address in memory
Standard Kotlin functions can be used as C callbacks
• As long as you convert the reference via ‘staticCFunction’
• Within the function you must call ‘initRuntimeIfNeeded()’
Explaining the Demo Code
pthread_create(threadHandle1.ptr,
attrs,
staticCFunction(::foobar),
data1.asCPointer())
37. In the code below we:
• Convert the opaque pointer to a StableRef of a Pair of values
• Convert the first value in the pair from a byte pointer to a String
• Specify default values for either item if it is missing
• Run the job of work to be done asynchronously
Explaining the Demo Code
val data = input?.asStableRef<Pair<CPointer<ByteVar>, pthread_mutex_t>>()
val name = data?.get()?.first?.toKString() ?: "No Name”
val dummy = alloc<pthread_mutex_t>()
val mutex = data?.get()?.second ?: dummy
for (x in 1..20) {
doWork(mutex, name, x)
}
38. Let Us Return To Normality
Let’s return to the normal world of sane people…
39. Kotlin Native has its own concurrency model
• Possible as JetBrains now has control of the underlying runtime
The main abstraction is a ‘Worker’
• Workers are similar to Actors in frameworks like Akka
You pass data and jobs to a worker via its ‘execute’ method
• The producer lambda returns a graph of objects whose
ownership will now be transferred to the target worker
• The calling thread won’t be able to access those objects
The Kotlin Native Concurrency Model
fun <T1, T2> execute(mode: TransferMode,
producer: () -> T1,
job: (T1) -> T2): Future<T2>
40. Objects in Kotlin Native can be frozen
• This is an operation that is performed at runtime
• All objects in a graph are marked as immutable
• Any writes result in an ‘InvalidMutabilityException’
Frozen objects can safely be shared between Workers
• Kotlin Native does not allow Workers to share mutable state
There are multiple ways to freeze an object:
• Singleton objects and enums are automatically frozen
• Arbitrary objects can be frozen via the ‘freeze’ method
• Global variables can be marked with ‘SharedImmutable’
Global variables can also be marked with ‘@ThreadLocal’
• In which case each Worker gets its own copy of the data
The Kotlin Native Concurrency Model