Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scala Native 0.5.x #47

Merged
merged 7 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ on:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Setup JDK
uses: actions/setup-java@v2
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
Expand Down
11 changes: 5 additions & 6 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
val scala3 = "3.1.1"
val scala213 = "2.13.4"
val scala212 = "2.12.13"
val scala211 = "2.11.12"
val scala3 = "3.3.3"
val scala213 = "2.13.14"
val scala212 = "2.12.19"

inThisBuild(
Seq(
organization := "com.github.lolgab",
version := "0.2.1",
scalaVersion := scala213,
crossScalaVersions := Seq(scala3, scala213, scala212, scala211),
crossScalaVersions := Seq(scala3, scala213, scala212)
)
)

Expand Down Expand Up @@ -39,7 +38,7 @@ lazy val commonSettings = Seq(
"-Xfatal-warnings",
// "-Wunused:imports"
),
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.7.11" % Test,
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.8.3" % Test,
testFrameworks += new TestFramework("utest.runner.Framework"),
)

Expand Down
26 changes: 5 additions & 21 deletions core/src/main/scala/scala/scalanative/loop/Eventloop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,22 @@ import scala.scalanative.unsafe._
import scala.scalanative.runtime._
import scala.scalanative.runtime.Intrinsics._
import scala.collection.mutable
import scala.scalanative.concurrent.NativeExecutionContext

object EventLoop {
import LibUV._, LibUVConstants._

val loop: LibUV.Loop = uv_default_loop()

// Schedule loop execution after main ends
scalanative.runtime.ExecutionContext.global.execute(
new Runnable {
def run(): Unit = EventLoop.run()
}
)

// Reference to the private queue of scala.scalanative.runtime.ExecutionContext
private val queue: mutable.ListBuffer[Runnable] = {
val executionContextPtr =
fromRawPtr[Byte](castObjectToRawPtr(ExecutionContext))
val queuePtr = !((executionContextPtr + 8).asInstanceOf[Ptr[Ptr[Byte]]])
castRawPtrToObject(toRawPtr(queuePtr))
.asInstanceOf[mutable.ListBuffer[Runnable]]
}
NativeExecutionContext.queue.execute { () => EventLoop.run() }

def run(): Unit = {
// scala.scalanative package private queue containing WorkStealing API
val queue = NativeExecutionContext.queueInternal
while (uv_loop_alive(loop) != 0 || queue.nonEmpty) {
while (queue.nonEmpty) {
val runnable = queue.remove(0)
try {
runnable.run()
} catch {
case t: Throwable =>
ExecutionContext.global.reportFailure(t)
}
queue.stealWork(1)
uv_run(loop, UV_RUN_NOWAIT)
}
uv_run(loop, UV_RUN_ONCE)
Expand Down
36 changes: 20 additions & 16 deletions core/src/main/scala/scala/scalanative/loop/Poll.scala
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
package scala.scalanative.loop

import scala.scalanative.libc.stdlib
import LibUV._, LibUVConstants._
import scala.scalanative.unsafe.Ptr
import scala.scalanative.unsafe.{Ptr, sizeOf}
import scala.scalanative.runtime.BlobArray
import internals.HandleUtils

class RWResult(val result: Int, val readable: Boolean, val writable: Boolean)
@inline class Poll(val ptr: Ptr[Byte]) extends AnyVal {
@inline class Poll(private val data: BlobArray) extends AnyVal {
private def handle: Ptr[Byte] = data.atUnsafe(0)

def start(in: Boolean, out: Boolean)(callback: RWResult => Unit): Unit = {
HandleUtils.setData(ptr, callback)
HandleUtils.setData(handle, callback)
var events = 0
if (out) events |= UV_WRITABLE
if (in) events |= UV_READABLE
uv_poll_start(ptr, events, Poll.pollReadWriteCB)
uv_poll_start(handle, events, Poll.pollReadWriteCB)
}

def startReadWrite(callback: RWResult => Unit): Unit = {
HandleUtils.setData(ptr, callback)
uv_poll_start(ptr, UV_READABLE | UV_WRITABLE, Poll.pollReadWriteCB)
HandleUtils.setData(handle, callback)
uv_poll_start(handle, UV_READABLE | UV_WRITABLE, Poll.pollReadWriteCB)
}

def startRead(callback: Int => Unit): Unit = {
HandleUtils.setData(ptr, callback)
uv_poll_start(ptr, UV_READABLE, Poll.pollReadCB)
HandleUtils.setData(handle, callback)
uv_poll_start(handle, UV_READABLE, Poll.pollReadCB)
}

def startWrite(callback: Int => Unit): Unit = {
HandleUtils.setData(ptr, callback)
uv_poll_start(ptr, UV_WRITABLE, Poll.pollWriteCB)
HandleUtils.setData(handle, callback)
uv_poll_start(handle, UV_WRITABLE, Poll.pollWriteCB)
}

def stop(): Unit = {
uv_poll_stop(ptr)
HandleUtils.close(ptr)
uv_poll_stop(handle)
HandleUtils.close(handle)
}
}

Expand Down Expand Up @@ -72,8 +74,10 @@ object Poll {
private lazy val size = uv_handle_size(UV_POLL_T)

def apply(fd: Int): Poll = {
val pollHandle = stdlib.malloc(size)
uv_poll_init(EventLoop.loop, pollHandle, fd)
new Poll(pollHandle)
// GC managed memory, but scans only user data
val data = BlobArray.alloc(size.toInt)
data.setScannableLimitUnsafe(sizeOf[Ptr[_]])
uv_poll_init(EventLoop.loop, data.atUnsafe(0), fd)
new Poll(data)
}
}
17 changes: 11 additions & 6 deletions core/src/main/scala/scala/scalanative/loop/Timer.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package scala.scalanative.loop

import scala.scalanative.libc.stdlib
import scala.concurrent.{Future, Promise}
import scala.concurrent.duration._
import LibUV._, LibUVConstants._
import scala.scalanative.unsafe.Ptr
import scala.scalanative.unsafe.{Ptr, sizeOf}
import scala.scalanative.runtime.BlobArray
import internals.HandleUtils

@inline final class Timer private (private val ptr: Ptr[Byte]) extends AnyVal {
@inline final class Timer private (private val data: BlobArray) extends AnyVal {
private def ptr = data.atUnsafe(0)
def clear(): Unit = {
uv_timer_stop(ptr)
HandleUtils.close(ptr)
Expand All @@ -29,17 +30,21 @@ object Timer {
repeat: Long,
callback: () => Unit
): Timer = {
val timerHandle = stdlib.malloc(uv_handle_size(UV_TIMER_T))
// GC managed memory, but scans only user data
val data = BlobArray.alloc(uv_handle_size(UV_TIMER_T).toInt)
data.setScannableLimitUnsafe(sizeOf[Ptr[_]])

val timerHandle = data.atUnsafe(0)
uv_timer_init(EventLoop.loop, timerHandle)
HandleUtils.setData(timerHandle, callback)
val timer = new Timer(timerHandle)
val timer = new Timer(data)
val withClearIfTimeout: () => Unit =
if (repeat == 0L) { () =>
{
callback()
timer.clear()
}
} else callback
HandleUtils.setData(timerHandle, withClearIfTimeout)
uv_timer_start(timerHandle, timeoutCB, timeout, repeat)
timer
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@ package internals
import scala.scalanative.runtime._
import scala.scalanative.runtime.Intrinsics._
import scala.scalanative.unsafe.Ptr
import scala.scalanative.libc.stdlib
import LibUV._

private[loop] object HandleUtils {
private val references = new java.util.IdentityHashMap[Object, Int]()

@inline def getData[T <: Object](handle: Ptr[Byte]): T = {
// data is the first member of uv_loop_t
val ptrOfPtr = handle.asInstanceOf[Ptr[Ptr[Byte]]]
Expand All @@ -24,23 +21,16 @@ private[loop] object HandleUtils {
// data is the first member of uv_loop_t
val ptrOfPtr = handle.asInstanceOf[Ptr[Ptr[Byte]]]
if (obj != null) {
references.put(obj, references.get(obj) + 1)
val rawptr = castObjectToRawPtr(obj)
!ptrOfPtr = fromRawPtr[Byte](rawptr)
} else {
!ptrOfPtr = null
}
}
private val onCloseCB: CloseCB = (handle: UVHandle) => {
stdlib.free(handle)
}
@inline def close(handle: Ptr[Byte]): Unit = {
if (getData(handle) != null) {
uv_close(handle, onCloseCB)
val data = getData[Object](handle)
val current = references.get(data)
if (current > 1) references.put(data, current - 1)
else references.remove(data)
val data = getData[Object](handle)
if (data != null) {
uv_close(handle, null)
setData(handle, null)
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/test/scala/scala/scalanative/loop/PollTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ object PollTests extends LoopTestSuite {
throw new Exception("Poll result != 0")
}
val buf = stackalloc[Byte]()
val bytesRead = read(r, buf, 1L.toULong)
val bytesRead = read(r, buf, 1L.toCSize)
assert(bytesRead == 1)
assert(buf(0) == byte)
promise.success(())
poll.stop()
}
val buf = stackalloc[Byte]()
buf(0) = byte
val bytesWrote = write(w, buf, 1L.toULong)
val bytesWrote = write(w, buf, 1L.toCSize)
assert(bytesWrote == 1)
promise.future
}
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.6.2
sbt.version=1.10.0
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.4")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.3")
addSbtPlugin("com.eed3si9n" % "sbt-dirty-money" % "0.2.0")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.4")
Expand Down