mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 11:18:02 +08:00
update comment for gmlock
This commit is contained in:
parent
d1f0fa1a47
commit
841224372b
@ -52,7 +52,10 @@ func (r *Response) buildInVars(params...map[string]interface{}) map[string]inter
|
||||
} else {
|
||||
vars = make(map[string]interface{})
|
||||
}
|
||||
vars["Config"] = gins.Config().GetMap("")
|
||||
// 当配置文件不存在时就不赋值该模板变量,不然会报错
|
||||
if c := gins.Config(); c.FilePath() != "" {
|
||||
vars["Config"] = c.GetMap("")
|
||||
}
|
||||
vars["Cookie"] = r.request.Cookie.Map()
|
||||
vars["Session"] = r.request.Session.Map()
|
||||
vars["Get"] = r.request.GetQueryMap()
|
||||
|
@ -20,10 +20,10 @@ import (
|
||||
|
||||
// SESSION对象
|
||||
type Session struct {
|
||||
id string // SessionId
|
||||
id string // SessionId
|
||||
data *gmap.StrAnyMap // Session数据
|
||||
server *Server // 所属Server
|
||||
request *Request // 关联的请求
|
||||
server *Server // 所属Server
|
||||
request *Request // 关联的请求
|
||||
}
|
||||
|
||||
// 生成一个唯一的SessionId字符串,长度18位。
|
||||
|
@ -55,20 +55,20 @@ func New(file...string) *Config {
|
||||
// Customized dir path from env/cmd.
|
||||
if envPath := cmdenv.Get("gf.gcfg.path").String(); envPath != "" {
|
||||
if gfile.Exists(envPath) {
|
||||
c.SetPath(envPath)
|
||||
_ = c.SetPath(envPath)
|
||||
} else {
|
||||
glog.Errorf("Configuration directory path does not exist: %s", envPath)
|
||||
}
|
||||
} else {
|
||||
// Dir path of working dir.
|
||||
c.SetPath(gfile.Pwd())
|
||||
_ = c.SetPath(gfile.Pwd())
|
||||
// Dir path of binary.
|
||||
if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) {
|
||||
c.AddPath(selfPath)
|
||||
_ = c.AddPath(selfPath)
|
||||
}
|
||||
// Dir path of main package.
|
||||
if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) {
|
||||
c.AddPath(mainPath)
|
||||
_ = c.AddPath(mainPath)
|
||||
}
|
||||
}
|
||||
return c
|
||||
|
@ -13,42 +13,62 @@ var (
|
||||
locker = New()
|
||||
)
|
||||
|
||||
// 内存写锁,如果锁成功返回true,失败则返回false;过期时间单位为秒,默认为0表示不过期
|
||||
// TryLock tries locking the <key> with write lock,
|
||||
// it returns true if success, or if there's a write/read lock the <key>,
|
||||
// it returns false. The parameter <expire> specifies the max duration it locks.
|
||||
func TryLock(key string, expire...time.Duration) bool {
|
||||
return locker.TryLock(key, expire...)
|
||||
}
|
||||
|
||||
// 内存写锁,锁成功返回true,失败时阻塞,当失败时表示有其他写锁存在;过期时间单位为秒,默认为0表示不过期
|
||||
// Lock locks the <key> with write lock.
|
||||
// If there's a write/read lock the <key>,
|
||||
// it will blocks until the lock is released.
|
||||
// The parameter <expire> specifies the max duration it locks.
|
||||
func Lock(key string, expire...time.Duration) {
|
||||
locker.Lock(key, expire...)
|
||||
}
|
||||
|
||||
// 解除基于内存锁的写锁
|
||||
// Unlock unlocks the write lock of the <key>.
|
||||
func Unlock(key string) {
|
||||
locker.Unlock(key)
|
||||
}
|
||||
|
||||
// 内存读锁,如果锁成功返回true,失败则返回false; 过期时间单位为秒,默认为0表示不过期
|
||||
// TryRLock tries locking the <key> with read lock.
|
||||
// It returns true if success, or if there's a write lock on <key>, it returns false.
|
||||
func TryRLock(key string) bool {
|
||||
return locker.TryRLock(key)
|
||||
}
|
||||
|
||||
// 内存写锁,锁成功返回true,失败时阻塞,当失败时表示有写锁存在; 过期时间单位为秒,默认为0表示不过期
|
||||
// RLock locks the <key> with read lock.
|
||||
// If there's a write lock on <key>,
|
||||
// it will blocks until the write lock is released.
|
||||
func RLock(key string) {
|
||||
locker.RLock(key)
|
||||
}
|
||||
|
||||
// 解除基于内存锁的读锁
|
||||
// RUnlock unlocks the read lock of the <key>.
|
||||
func RUnlock(key string) {
|
||||
locker.RUnlock(key)
|
||||
}
|
||||
|
||||
// 通过闭包的方式写锁执行回调方法<f>,执行完毕后释放写锁
|
||||
// LockFunc locks the <key> with write lock and callback function <f>.
|
||||
// If there's a write/read lock the <key>,
|
||||
// it will blocks until the lock is released.
|
||||
//
|
||||
// It releases the lock after <f> is executed.
|
||||
//
|
||||
// The parameter <expire> specifies the max duration it locks.
|
||||
func LockFunc(key string, f func(), expire...time.Duration) {
|
||||
locker.LockFunc(key, f, expire...)
|
||||
}
|
||||
|
||||
// 通过闭包的方式读锁执行回调方法<f>,执行完毕后释放读锁
|
||||
// RLockFunc locks the <key> with read lock and callback function <f>.
|
||||
// If there's a write lock the <key>,
|
||||
// it will blocks until the lock is released.
|
||||
//
|
||||
// It releases the lock after <f> is executed.
|
||||
//
|
||||
// The parameter <expire> specifies the max duration it locks.
|
||||
func RLockFunc(key string, f func()) {
|
||||
locker.RLockFunc(key, f)
|
||||
}
|
@ -12,67 +12,89 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// 内存锁管理对象
|
||||
// Memory locker.
|
||||
type Locker struct {
|
||||
m *gmap.StrAnyMap
|
||||
}
|
||||
|
||||
// 创建一把内存锁, 底层使用的是Mutex
|
||||
// New creates and returns a new memory locker.
|
||||
// A memory locker can lock/unlock with dynamic string key.
|
||||
func New() *Locker {
|
||||
return &Locker{
|
||||
m : gmap.NewStrAnyMap(),
|
||||
}
|
||||
}
|
||||
|
||||
// 内存写锁,如果锁成功返回true,失败则返回false; 过期时间默认为0表示不过期
|
||||
// TryLock tries locking the <key> with write lock,
|
||||
// it returns true if success, or if there's a write/read lock the <key>,
|
||||
// it returns false. The parameter <expire> specifies the max duration it locks.
|
||||
func (l *Locker) TryLock(key string, expire...time.Duration) bool {
|
||||
return l.doLock(key, l.getExpire(expire...), true)
|
||||
}
|
||||
|
||||
// 内存写锁,锁成功返回true,失败时阻塞,当失败时表示有其他写锁存在;过期时间默认为0表示不过期
|
||||
// Lock locks the <key> with write lock.
|
||||
// If there's a write/read lock the <key>,
|
||||
// it will blocks until the lock is released.
|
||||
// The parameter <expire> specifies the max duration it locks.
|
||||
func (l *Locker) Lock(key string, expire...time.Duration) {
|
||||
l.doLock(key, l.getExpire(expire...), false)
|
||||
}
|
||||
|
||||
// 解除基于内存锁的写锁
|
||||
// Unlock unlocks the write lock of the <key>.
|
||||
func (l *Locker) Unlock(key string) {
|
||||
if v := l.m.Get(key); v != nil {
|
||||
v.(*Mutex).Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// 内存读锁,如果锁成功返回true,失败则返回false; 过期时间单位为秒,默认为0表示不过期
|
||||
// TryRLock tries locking the <key> with read lock.
|
||||
// It returns true if success, or if there's a write lock on <key>, it returns false.
|
||||
func (l *Locker) TryRLock(key string) bool {
|
||||
return l.doRLock(key, true)
|
||||
}
|
||||
|
||||
// 内存写锁,锁成功返回true,失败时阻塞,当失败时表示有写锁存在; 过期时间单位为秒,默认为0表示不过期
|
||||
// RLock locks the <key> with read lock.
|
||||
// If there's a write lock on <key>,
|
||||
// it will blocks until the write lock is released.
|
||||
func (l *Locker) RLock(key string) {
|
||||
l.doRLock(key, false)
|
||||
}
|
||||
|
||||
// 解除基于内存锁的读锁
|
||||
// RUnlock unlocks the read lock of the <key>.
|
||||
func (l *Locker) RUnlock(key string) {
|
||||
if v := l.m.Get(key); v != nil {
|
||||
v.(*Mutex).RUnlock()
|
||||
}
|
||||
}
|
||||
|
||||
// 通过闭包的方式写锁执行回调方法<f>,执行完毕后释放写锁
|
||||
// LockFunc locks the <key> with write lock and callback function <f>.
|
||||
// If there's a write/read lock the <key>,
|
||||
// it will blocks until the lock is released.
|
||||
//
|
||||
// It releases the lock after <f> is executed.
|
||||
//
|
||||
// The parameter <expire> specifies the max duration it locks.
|
||||
func (l *Locker) LockFunc(key string, f func(), expire...time.Duration) {
|
||||
l.Lock(key, expire...)
|
||||
defer l.Unlock(key)
|
||||
f()
|
||||
}
|
||||
|
||||
// 通过闭包的方式读锁执行回调方法<f>,执行完毕后释放读锁
|
||||
// RLockFunc locks the <key> with read lock and callback function <f>.
|
||||
// If there's a write lock the <key>,
|
||||
// it will blocks until the lock is released.
|
||||
//
|
||||
// It releases the lock after <f> is executed.
|
||||
//
|
||||
// The parameter <expire> specifies the max duration it locks.
|
||||
func (l *Locker) RLockFunc(key string, f func()) {
|
||||
l.RLock(key)
|
||||
defer l.RUnlock(key)
|
||||
f()
|
||||
}
|
||||
|
||||
// 获得过期时间,没有设置时默认为0不过期
|
||||
// getExpire returns the duration object passed.
|
||||
// If <expire> is not passed, it returns a default duration object.
|
||||
func (l *Locker) getExpire(expire...time.Duration) time.Duration {
|
||||
e := time.Duration(0)
|
||||
if len(expire) > 0 {
|
||||
@ -81,7 +103,14 @@ func (l *Locker) getExpire(expire...time.Duration) time.Duration {
|
||||
return e
|
||||
}
|
||||
|
||||
// 内存写锁,当try==true时,如果锁成功返回true,失败则返回false;try==false时,成功时立即返回,否则阻塞等待
|
||||
// doLock locks writing on <key>.
|
||||
// It returns true if success, or else returns false.
|
||||
//
|
||||
// The parameter <try> is true,
|
||||
// it returns false immediately if it fails getting the write lock.
|
||||
// If <true> is false, it blocks until it gets the write lock.
|
||||
//
|
||||
// The parameter <expire> specifies the max duration it locks.
|
||||
func (l *Locker) doLock(key string, expire time.Duration, try bool) bool {
|
||||
mu := l.getOrNewMutex(key)
|
||||
ok := true
|
||||
@ -102,7 +131,12 @@ func (l *Locker) doLock(key string, expire time.Duration, try bool) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// 内存读锁,当try==true时,如果锁成功返回true,失败则返回false;try==false时,成功时立即返回,否则阻塞等待
|
||||
// doRLock locks reading on <key>.
|
||||
// It returns true if success, or else returns false.
|
||||
//
|
||||
// The parameter <try> is true,
|
||||
// it returns false immediately if it fails getting the read lock.
|
||||
// If <true> is false, it blocks until it gets the read lock.
|
||||
func (l *Locker) doRLock(key string, try bool) bool {
|
||||
mu := l.getOrNewMutex(key)
|
||||
ok := true
|
||||
@ -114,8 +148,9 @@ func (l *Locker) doRLock(key string, try bool) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// 根据指定key查询或者创建新的Mutex
|
||||
func (l *Locker) getOrNewMutex(key string) (*Mutex) {
|
||||
// getOrNewMutex returns the mutex of given <key> if it exists,
|
||||
// or else creates and returns a new one.
|
||||
func (l *Locker) getOrNewMutex(key string) *Mutex {
|
||||
return l.m.GetOrSetFuncLock(key, func() interface{} {
|
||||
return NewMutex()
|
||||
}).(*Mutex)
|
||||
|
@ -11,15 +11,15 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 互斥锁对象
|
||||
// The mutex.
|
||||
type Mutex struct {
|
||||
mu sync.RWMutex
|
||||
wid *gtype.Int64 // 当前Lock产生的唯一id(主要用于计时Unlock的校验)
|
||||
rcount *gtype.Int // RLock次数
|
||||
wcount *gtype.Int // Lock次数
|
||||
wid *gtype.Int64 // Unique id for this mutex.
|
||||
rcount *gtype.Int // RLock count.
|
||||
wcount *gtype.Int // Lock count.
|
||||
}
|
||||
|
||||
// 创建一把内存锁使用的底层RWMutex
|
||||
// NewMutex creates and returns a new mutex.
|
||||
func NewMutex() *Mutex {
|
||||
return &Mutex{
|
||||
wid : gtype.NewInt64(),
|
||||
@ -28,46 +28,55 @@ func NewMutex() *Mutex {
|
||||
}
|
||||
}
|
||||
|
||||
// Lock locks mutex for writing.
|
||||
// If the lock is already locked for reading or writing,
|
||||
// Lock blocks until the lock is available.
|
||||
func (l *Mutex) Lock() {
|
||||
l.wcount.Add(1)
|
||||
l.mu.Lock()
|
||||
l.wid.Add(1)
|
||||
}
|
||||
|
||||
// 安全的Unlock
|
||||
// Unlock unlocks the write lock.
|
||||
// It is safe to be called multiple times.
|
||||
func (l *Mutex) Unlock() {
|
||||
if l.wcount.Val() > 0 {
|
||||
if l.wcount.Add(-1) >= 0 {
|
||||
l.mu.Unlock()
|
||||
} else {
|
||||
// 标准库这里会panic
|
||||
l.wcount.Add(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RLock locks mutex for reading.
|
||||
func (l *Mutex) RLock() {
|
||||
l.rcount.Add(1)
|
||||
l.mu.RLock()
|
||||
}
|
||||
|
||||
// 安全的RUnlock
|
||||
// RUnlock undoes a single RLock call;
|
||||
// it does not affect other simultaneous readers.
|
||||
// It is a run-time error if rw is not locked for reading
|
||||
// on entry to RUnlock.
|
||||
// It is safe to be called multiple times.
|
||||
func (l *Mutex) RUnlock() {
|
||||
if l.rcount.Val() > 0 {
|
||||
if l.rcount.Add(-1) >= 0 {
|
||||
l.mu.RUnlock()
|
||||
} else {
|
||||
// 标准库这里会panic
|
||||
l.rcount.Add(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 不阻塞Lock
|
||||
// TryLock tries locking the mutex with write lock,
|
||||
// it returns true if success, or if there's a write/read lock the mutex,
|
||||
// it returns false.
|
||||
func (l *Mutex) TryLock() bool {
|
||||
// 初步读写次数检查, 但无法保证原子性
|
||||
// The first check, but it cannot ensure the atomicity.
|
||||
if l.wcount.Val() == 0 && l.rcount.Val() == 0 {
|
||||
// 第二次检查, 保证原子操作
|
||||
// The second check, it can ensure the atomicity.
|
||||
if l.wcount.Add(1) == 1 {
|
||||
l.mu.Lock()
|
||||
l.wid.Add(1)
|
||||
@ -79,9 +88,10 @@ func (l *Mutex) TryLock() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 不阻塞RLock
|
||||
// TryRLock tries locking the mutex with read lock.
|
||||
// It returns true if success, or if there's a write lock on mutex, it returns false.
|
||||
func (l *Mutex) TryRLock() bool {
|
||||
// 只要不存在写锁
|
||||
// There must be no write lock on mutex.
|
||||
if l.wcount.Val() == 0 {
|
||||
l.rcount.Add(1)
|
||||
l.mu.RLock()
|
||||
|
@ -21,6 +21,11 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const (
|
||||
// Template name for content parsing.
|
||||
gCONTENT_TEMPLATE_NAME = "template content"
|
||||
)
|
||||
|
||||
var (
|
||||
// Templates cache map for template folder.
|
||||
templates = gmap.NewStrAnyMap()
|
||||
@ -103,7 +108,8 @@ func (view *View) Parse(file string, params...Params) (parsed string, err error)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
gmlock.LockFunc("gview-template-parsing:" + folder, func() {
|
||||
// Using memory lock to ensure concurrent safety for template parsing.
|
||||
gmlock.LockFunc("gview-parsing:" + folder, func() {
|
||||
tpl, err = tpl.Parse(gfcache.GetContents(path))
|
||||
})
|
||||
if err != nil {
|
||||
@ -149,8 +155,14 @@ func (view *View) Parse(file string, params...Params) (parsed string, err error)
|
||||
func (view *View) ParseContent(content string, params...Params) (string, error) {
|
||||
view.mu.RLock()
|
||||
defer view.mu.RUnlock()
|
||||
tpl := template.New("template content").Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcMap)
|
||||
tpl, err := tpl.Parse(content)
|
||||
err := (error)(nil)
|
||||
tpl := templates.GetOrSetFuncLock(gCONTENT_TEMPLATE_NAME, func() interface {} {
|
||||
return template.New(gCONTENT_TEMPLATE_NAME).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcMap)
|
||||
}).(*template.Template)
|
||||
// Using memory lock to ensure concurrent safety for content parsing.
|
||||
gmlock.LockFunc("gview-parsing:content", func() {
|
||||
tpl, err = tpl.Parse(content)
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -3,20 +3,15 @@ package main
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/os/gcache"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.BindHandler("/", func(r *ghttp.Request) {
|
||||
rs :="GF(Go Frame)是一款模块化、松耦合、生产级的Go应用开发框架。提供了常用的核心开发组件,如:缓存、日志、文件、时间、队列、数组、集合、字符串、定时器、命令行、文件锁、内存锁、对象池、连接池、数据校验、数据编码、文件监控、定时任务、数据库ORM、TCP/UDP组件、进程管理/通信、 并发安全容器等等。并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、路由注册、配置管理、模板引擎等等,支持热重启、热更新、多域名、多端口、多服务、HTTPS、Rewrite等特性。"
|
||||
Weijin_word := gcache.Get("weijin_word")
|
||||
if Weijin_word == nil {
|
||||
Weijin_word = gcache.GetOrSet("weijin_word", rs, 0)
|
||||
}
|
||||
//此行压测会提示map并发错误 webbench -c 8000 -t 60 http://IP 局域网两台机器测试
|
||||
r.Response.WriteTpl("layout.html", g.Map{
|
||||
"Contentb": Weijin_word,
|
||||
r.Response.WriteTplContent(rs, g.Map{
|
||||
"Contentb": 1,
|
||||
})
|
||||
})
|
||||
s.SetPort(8199)
|
||||
|
Loading…
Reference in New Issue
Block a user