Merge pull request #437 from xushiwei/q

runtime: chan; cmptest: iodemo, fmtdemo
This commit is contained in:
xushiwei
2024-07-02 16:05:14 +08:00
committed by GitHub
5 changed files with 177 additions and 0 deletions

View File

@@ -217,6 +217,7 @@ Here are the Go packages that can be imported correctly:
* [io](https://pkg.go.dev/io) (partially)
* [io/fs](https://pkg.go.dev/io/fs) (partially)
* [os](https://pkg.go.dev/os) (partially)
* [fmt](https://pkg.go.dev/fmt) (partially)
* [reflect](https://pkg.go.dev/reflect) (partially)
* [time](https://pkg.go.dev/time) (partially)

26
_demo/cchan/cchan.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"unsafe"
"github.com/goplus/llgo/internal/runtime"
)
const (
eltSize = int(unsafe.Sizeof(0))
)
func doChan(cap int) {
c := runtime.NewChan(eltSize, cap)
go func() {
v := 100
runtime.ChanSend(c, unsafe.Pointer(&v), eltSize)
}()
var ret int
runtime.ChanRecv(c, unsafe.Pointer(&ret), eltSize)
println(ret)
}
func main() {
doChan(10)
}

150
internal/runtime/z_chan.go Normal file
View File

@@ -0,0 +1,150 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package runtime
import (
"unsafe"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/pthread/sync"
)
// -----------------------------------------------------------------------------
const chanFull = 1
type Chan struct {
mutex sync.Mutex
cond sync.Cond
data unsafe.Pointer
getp int
len int
cap int
}
func NewChan(eltSize, cap int) *Chan {
ret := new(Chan)
if cap > 0 {
ret.data = AllocU(uintptr(cap * eltSize))
ret.cap = cap
}
ret.cond.Init(nil)
return ret
}
func ChanLen(p *Chan) (n int) {
p.mutex.Lock()
n = p.len
p.mutex.Unlock()
return
}
func ChanCap(p *Chan) int {
return p.cap
}
func ChanTrySend(p *Chan, v unsafe.Pointer, eltSize int) bool {
n := p.cap
p.mutex.Lock()
if n == 0 {
if p.getp == chanFull {
p.mutex.Unlock()
return false
}
p.data = v
p.getp = chanFull
} else {
if p.len == n {
p.mutex.Unlock()
return false
}
off := (p.getp + p.len) % n
c.Memcpy(c.Advance(p.data, off*eltSize), v, uintptr(eltSize))
p.len++
}
p.mutex.Unlock()
p.cond.Broadcast()
return true
}
func ChanSend(p *Chan, v unsafe.Pointer, eltSize int) {
n := p.cap
p.mutex.Lock()
if n == 0 {
for p.getp == chanFull {
p.cond.Wait(&p.mutex)
}
p.data = v
p.getp = chanFull
} else {
for p.len == n {
p.cond.Wait(&p.mutex)
}
off := (p.getp + p.len) % n
c.Memcpy(c.Advance(p.data, off*eltSize), v, uintptr(eltSize))
p.len++
}
p.mutex.Unlock()
p.cond.Broadcast()
}
func ChanTryRecv(p *Chan, v unsafe.Pointer, eltSize int) bool {
n := p.cap
p.mutex.Lock()
if n == 0 {
if p.getp == 0 {
p.mutex.Unlock()
return false
}
c.Memcpy(v, p.data, uintptr(eltSize))
p.getp = 0
} else {
if p.len == 0 {
p.mutex.Unlock()
return false
}
c.Memcpy(v, c.Advance(p.data, p.getp*eltSize), uintptr(eltSize))
p.getp = (p.getp + 1) % n
p.len--
}
p.mutex.Unlock()
p.cond.Broadcast()
return true
}
func ChanRecv(p *Chan, v unsafe.Pointer, eltSize int) {
n := p.cap
p.mutex.Lock()
if n == 0 {
for p.getp == 0 {
p.cond.Wait(&p.mutex)
}
c.Memcpy(v, p.data, uintptr(eltSize))
p.getp = 0
} else {
for p.len == 0 {
p.cond.Wait(&p.mutex)
}
c.Memcpy(v, c.Advance(p.data, p.getp*eltSize), uintptr(eltSize))
p.getp = (p.getp + 1) % n
p.len--
}
p.mutex.Unlock()
p.cond.Broadcast()
}
// -----------------------------------------------------------------------------