From 61c067c6618e9f2942cfbe11bb1bac84a9d18508 Mon Sep 17 00:00:00 2001 From: John Date: Sat, 20 Jan 2018 11:09:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8A=A8=E6=80=81=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F=E7=9A=84=E5=AE=89=E5=85=A8=E9=98=9F=E5=88=97gqueue?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E4=BF=AE=E6=AD=A3grpool=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E6=95=B0=E9=87=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/container/gqueue/int_queue.go | 54 ++++++++++++++++++++++++++ g/container/gqueue/interface_queue.go | 55 +++++++++++++++++++++++++++ g/container/gqueue/string_queue.go | 54 ++++++++++++++++++++++++++ g/container/gqueue/uint_queue.go | 54 ++++++++++++++++++++++++++ g/encoding/gjson/gjson.go | 22 ++++++++--- g/encoding/gtoml/gtoml.go | 42 ++++++++++++++++++++ g/encoding/gyaml/gyaml.go | 7 +++- g/frame/gins/gins.go | 6 +-- g/{frame => os}/gcfg/gcfg.go | 2 +- g/os/grpool/grpool_api.go | 2 +- geg/container/gqueue.go | 32 ++++++++++++++++ geg/other/test.go | 13 +++++-- 12 files changed, 327 insertions(+), 16 deletions(-) create mode 100644 g/container/gqueue/int_queue.go create mode 100644 g/container/gqueue/interface_queue.go create mode 100644 g/container/gqueue/string_queue.go create mode 100644 g/container/gqueue/uint_queue.go create mode 100644 g/encoding/gtoml/gtoml.go rename g/{frame => os}/gcfg/gcfg.go (98%) create mode 100644 geg/container/gqueue.go diff --git a/g/container/gqueue/int_queue.go b/g/container/gqueue/int_queue.go new file mode 100644 index 000000000..794004ee7 --- /dev/null +++ b/g/container/gqueue/int_queue.go @@ -0,0 +1,54 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package gqueue + +import ( + "math" + "sync" + "container/list" +) + +type IntQueue struct { + mu sync.RWMutex + list *list.List + events chan struct{} +} + +func NewIntQueue() *IntQueue { + return &IntQueue{ + list : list.New(), + events : make(chan struct{}, math.MaxInt64), + } +} + +// 将数据压入队列 +func (q *IntQueue) Push(v int) { + q.mu.Lock() + q.list.PushBack(v) + q.mu.Unlock() + q.events <- struct{}{} +} + +// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待 +func (q *IntQueue) Pop() int { + select { + case <- q.events: + q.mu.Lock() + if elem := q.list.Front(); elem != nil { + item := q.list.Remove(elem).(int) + q.mu.Unlock() + return item + } + q.mu.Unlock() + } + return 0 +} + +// 获取当前队列大小 +func (q *IntQueue) Size() int { + return len(q.events) +} \ No newline at end of file diff --git a/g/container/gqueue/interface_queue.go b/g/container/gqueue/interface_queue.go new file mode 100644 index 000000000..7c6122f23 --- /dev/null +++ b/g/container/gqueue/interface_queue.go @@ -0,0 +1,55 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +// 动态大小的安全队列(dynamic channel). +package gqueue + +import ( + "math" + "sync" + "container/list" +) + +type InterfaceQueue struct { + mu sync.RWMutex + list *list.List + events chan struct{} +} + +func NewInterfaceQueue() *InterfaceQueue { + return &InterfaceQueue { + list : list.New(), + events : make(chan struct{}, math.MaxInt64), + } +} + +// 将数据压入队列 +func (q *InterfaceQueue) Push(v interface{}) { + q.mu.Lock() + q.list.PushBack(v) + q.mu.Unlock() + q.events <- struct{}{} +} + +// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待 +func (q *InterfaceQueue) Pop() interface{} { + select { + case <- q.events: + q.mu.Lock() + if elem := q.list.Front(); elem != nil { + item := q.list.Remove(elem) + q.mu.Unlock() + return item + } + q.mu.Unlock() + } + return nil +} + +// 获取当前队列大小 +func (q *InterfaceQueue) Size() int { + return len(q.events) +} \ No newline at end of file diff --git a/g/container/gqueue/string_queue.go b/g/container/gqueue/string_queue.go new file mode 100644 index 000000000..fb67c0c0c --- /dev/null +++ b/g/container/gqueue/string_queue.go @@ -0,0 +1,54 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package gqueue + +import ( + "math" + "sync" + "container/list" +) + +type StringQueue struct { + mu sync.RWMutex + list *list.List + events chan struct{} +} + +func NewStringQueue() *StringQueue { + return &StringQueue{ + list : list.New(), + events : make(chan struct{}, math.MaxInt64), + } +} + +// 将数据压入队列 +func (q *StringQueue) Push(v string) { + q.mu.Lock() + q.list.PushBack(v) + q.mu.Unlock() + q.events <- struct{}{} +} + +// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待 +func (q *StringQueue) Pop() string { + select { + case <- q.events: + q.mu.Lock() + if elem := q.list.Front(); elem != nil { + item := q.list.Remove(elem).(string) + q.mu.Unlock() + return item + } + q.mu.Unlock() + } + return "" +} + +// 获取当前队列大小 +func (q *StringQueue) Size() int { + return len(q.events) +} \ No newline at end of file diff --git a/g/container/gqueue/uint_queue.go b/g/container/gqueue/uint_queue.go new file mode 100644 index 000000000..601ffb59e --- /dev/null +++ b/g/container/gqueue/uint_queue.go @@ -0,0 +1,54 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package gqueue + +import ( + "math" + "sync" + "container/list" +) + +type UintQueue struct { + mu sync.RWMutex + list *list.List + events chan struct{} +} + +func NewUintQueue() *UintQueue { + return &UintQueue{ + list : list.New(), + events : make(chan struct{}, math.MaxInt64), + } +} + +// 将数据压入队列 +func (q *UintQueue) Push(v uint) { + q.mu.Lock() + q.list.PushBack(v) + q.mu.Unlock() + q.events <- struct{}{} +} + +// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待 +func (q *UintQueue) Pop() uint { + select { + case <- q.events: + q.mu.Lock() + if elem := q.list.Front(); elem != nil { + item := q.list.Remove(elem).(uint) + q.mu.Unlock() + return item + } + q.mu.Unlock() + } + return 0 +} + +// 获取当前队列大小 +func (q *UintQueue) Size() int { + return len(q.events) +} \ No newline at end of file diff --git a/g/encoding/gjson/gjson.go b/g/encoding/gjson/gjson.go index 3f028fb9f..3712459b5 100644 --- a/g/encoding/gjson/gjson.go +++ b/g/encoding/gjson/gjson.go @@ -16,6 +16,7 @@ import ( "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g/encoding/gxml" "gitee.com/johng/gf/g/encoding/gyaml" + "gitee.com/johng/gf/g/encoding/gtoml" ) // json解析结果存放数组 @@ -65,25 +66,32 @@ func Load (path string) (*Json, error) { return LoadContent(data, gfile.Ext(path)) } -// 支持的配置文件格式:xml, json, yml +// 支持的配置文件格式:xml, json, yaml/yml, toml func LoadContent (data []byte, t string) (*Json, error) { var err error var result interface{} switch t { - case "xml": fallthrough + case "xml": fallthrough case ".xml": data, err = gxml.ToJson(data) if err != nil { return nil, err } - case "yml": fallthrough - case "yaml": fallthrough - case ".yml": fallthrough + case "yml": fallthrough + case "yaml": fallthrough + case ".yml": fallthrough case ".yaml": data, err = gyaml.ToJson(data) if err != nil { return nil, err } + + case "toml": fallthrough + case ".toml": + data, err = gtoml.ToJson(data) + if err != nil { + return nil, err + } } if err := json.Unmarshal(data, &result); err != nil { return nil, err @@ -252,6 +260,10 @@ func (p *Json) ToYaml() ([]byte, error) { return gyaml.Encode(*(p.value)) } +func (p *Json) ToToml() ([]byte, error) { + return gtoml.Encode(*(p.value)) +} + // 判断所给字符串是否为数字 func isNumeric(s string) bool { for i := 0; i < len(s); i++ { diff --git a/g/encoding/gtoml/gtoml.go b/g/encoding/gtoml/gtoml.go new file mode 100644 index 000000000..2e50a4b8a --- /dev/null +++ b/g/encoding/gtoml/gtoml.go @@ -0,0 +1,42 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +// TOML +package gtoml + +import ( + "bytes" + "encoding/json" + "github.com/BurntSushi/toml" +) + +func Encode(v interface{}) ([]byte, error) { + buffer := bytes.NewBuffer(nil) + if err := toml.NewEncoder(buffer).Encode(v); err != nil { + return nil, err + } + return buffer.Bytes(), nil +} + +func Decode(v []byte) (interface{}, error) { + var result interface{} + if err := toml.Unmarshal(v, &result); err != nil { + return nil, err + } + return result, nil +} + +func DecodeTo(v []byte, result interface{}) error { + return toml.Unmarshal(v, result) +} + +func ToJson(v []byte) ([]byte, error) { + if r, err := Decode(v); err != nil { + return nil, err + } else { + return json.Marshal(r) + } +} \ No newline at end of file diff --git a/g/encoding/gyaml/gyaml.go b/g/encoding/gyaml/gyaml.go index 356e25d26..0371b69ec 100644 --- a/g/encoding/gyaml/gyaml.go +++ b/g/encoding/gyaml/gyaml.go @@ -13,9 +13,12 @@ func Encode(v interface{}) ([]byte, error) { return yaml.Marshal(v) } -func Decode(v []byte) error { +func Decode(v []byte) (interface{}, error) { var result interface{} - return yaml.Unmarshal(v, &result) + if err := yaml.Unmarshal(v, &result); err != nil { + return nil, err + } + return result, nil } func DecodeTo(v []byte, result interface{}) error { diff --git a/g/frame/gins/gins.go b/g/frame/gins/gins.go index ef94d27f3..f3288a6b0 100644 --- a/g/frame/gins/gins.go +++ b/g/frame/gins/gins.go @@ -4,18 +4,18 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. -// 单例对象管理. -// 框架内置了一些核心对象,并且可以通过Set和Get方法实现IoC以及对内置核心对象的自定义替换 +// 单例对象管理(耦合了一些框架核心对象获取方法). +// 框架内置了一些核心对象获取方法,并且可以通过Set和Get方法实现IoC以及对内置核心对象的自定义替换 package gins import ( "strconv" + "gitee.com/johng/gf/g/os/gcfg" "gitee.com/johng/gf/g/os/gcmd" "gitee.com/johng/gf/g/os/glog" "gitee.com/johng/gf/g/os/genv" "gitee.com/johng/gf/g/os/gview" "gitee.com/johng/gf/g/os/gfile" - "gitee.com/johng/gf/g/frame/gcfg" "gitee.com/johng/gf/g/database/gdb" "gitee.com/johng/gf/g/container/gmap" ) diff --git a/g/frame/gcfg/gcfg.go b/g/os/gcfg/gcfg.go similarity index 98% rename from g/frame/gcfg/gcfg.go rename to g/os/gcfg/gcfg.go index 75c2aaeb6..9f72aa175 100644 --- a/g/frame/gcfg/gcfg.go +++ b/g/os/gcfg/gcfg.go @@ -5,7 +5,7 @@ // You can obtain one at https://gitee.com/johng/gf. // 配置管理. -// 配置文件格式支持:json, xml, yml +// 配置文件格式支持:json, xml, toml, yaml/yml package gcfg import ( diff --git a/g/os/grpool/grpool_api.go b/g/os/grpool/grpool_api.go index e3d66bd8f..773fabdb1 100644 --- a/g/os/grpool/grpool_api.go +++ b/g/os/grpool/grpool_api.go @@ -56,7 +56,7 @@ func New(expire int, sizes...int) *Pool { funcs : glist.NewSafeList(), freeEvents : make(chan struct{}, math.MaxUint32), funcEvents : make(chan struct{}, math.MaxUint32), - stopEvents : make(chan struct{}, 1), + stopEvents : make(chan struct{}, 2), } p.startWorkLoop() p.startClearLoop() diff --git a/geg/container/gqueue.go b/geg/container/gqueue.go new file mode 100644 index 000000000..f85a62ed3 --- /dev/null +++ b/geg/container/gqueue.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "gitee.com/johng/gf/g/os/gtime" + "gitee.com/johng/gf/g/container/gqueue" + "time" +) + +func main() { + t := gtime.Microsecond() + q := gqueue.NewInterfaceQueue() + fmt.Println("queue creation costs(μs):", gtime.Microsecond() - t) + + // 每隔2秒异步打印出当前队列的大小 + gtime.SetInterval(2*time.Second, func() bool { + fmt.Println("queue size:", q.Size()) + return true + }) + + // push10条数据 + for i := 0; i < 10; i++ { + q.Push(i) + fmt.Println("push:", i) + } + + // 每隔1秒pop1条数据 + for { + time.Sleep(time.Second) + fmt.Println(" pop:", q.Pop()) + } +} diff --git a/geg/other/test.go b/geg/other/test.go index d04c615bd..6ebb57f03 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -2,11 +2,16 @@ package main import ( "fmt" - "gitee.com/johng/gf/g/encoding/gjson" ) func main() { - j, _ := gjson.Load("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame/config.json") - c, _ := j.ToXmlIndent("config") - fmt.Println(string(c)) + c1 := make(chan int, 2) + c2 := make(chan int, 5) + c1 <- 1 + c1 <- 2 + c2 = c1 + c2 <- 3 + fmt.Println(<-c2) + fmt.Println(<-c2) + fmt.Println(<-c2) } \ No newline at end of file