idealvin / coost Goto Github PK
View Code? Open in Web Editor NEWA tiny boost library in C++11.
License: Other
A tiny boost library in C++11.
License: Other
#include "co/co.h"
#include "co/log.h"
#include "co/time.h"
co::Event ev;
DEF_bool(wait_alway, true, "false: wait for timeout, true wait alway");
void f2(){
CLOG << "f2() start";
bool r = true;
if (FLG_wait_alway) {
ev.wait();
} else {
r = ev.wait(1*1000);
}
CLOG << "f2() end: " << r;
}
void f3() {
CLOG << "f3() start";
ev.signal();
CLOG << "f3() end";
}
int main(int argc, char** argv) {
flag::init(argc, argv);
log::init();
go(f2);
sleep::ms(100);
go(f3);
sleep::ms(2*1000);
return 0;
}
运行结果1:
./test wait_alway=false
f2() start
f3() start
f3() end
f2() end: true
运行结果1:
./test wait_alway=true
f2() start
f3() start
f3() end
Under co/base/
:
$ xmake f -a x86
checking for the Microsoft Visual Studio (x86) version ... 2019
$ xmake
[ 23%]: compiling.release co\impl\epoll.cc
[ 26%]: compiling.release co\impl\co_win.cpp
[ 29%]: compiling.release stack_trace\stack_trace_win.cpp
[ 33%]: compiling.release win\time.cpp
[ 39%]: compiling.release fast.cc
[ 6%]: compiling.release fastring.cc
[ 9%]: compiling.release hash\base64.cc
[ 16%]: compiling.release co\impl\co_unix.cc
[ 19%]: compiling.release json.cc
[ 42%]: compiling.release co\impl\scheduler.cc
[ 46%]: compiling.release unix\time.cc
[ 49%]: compiling.release win\os.cpp
[ 52%]: compiling.release str.cc
error: time.cpp
C:\Users\fzheng\source\repos\co\base\win/atomic.h(46): error C3861: '_InterlockedIncrement64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(62): error C3861: '_InterlockedDecrement64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(78): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(94): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(110): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(126): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(142): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(158): error C3861: '_InterlockedExchangeAdd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(174): error C3861: '_InterlockedOr64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(190): error C3861: '_InterlockedAnd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(206): error C3861: '_InterlockedXor64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(222): error C3861: '_InterlockedOr64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(238): error C3861: '_InterlockedAnd64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(254): error C3861: '_InterlockedXor64': identifier not found
C:\Users\fzheng\source\repos\co\base\win/atomic.h(270): error C3861: '_InterlockedExchange64': identifier not found
// The key is not inserted if it already exists.
void insert(const K& key, const V& value) {
auto r = _kv.insert(std::make_pair(key, value));
if (!r.second) return;
_kl.push_front(key);
_ki[key] = _kl.begin();
if (_kv.size() > _capacity) {
K k = _kl.back();
_kl.pop_back();
_kv.erase(k);
_ki.erase(k);
}
}
当缓存中已有key时,insert不会有任何操作,如果我想更新一个key的value时该怎么办,并且_kl中的顺序也要改变。
index 9d2a6e3..c09f622 100644
--- a/src/hash/base64.cc
+++ b/src/hash/base64.cc
@@ -3,7 +3,7 @@
static const char* entab =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char detab[256] = {
+static const int8_t detab[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
本库引入了定长整数类型别名。但有一些处理让我觉得困惑:
fastring
的内部引用计数类需要假定unsigned int
的长度;Random
的整个操作看起来需要依赖标准整数类型的长度;这些地方是不是直接使用定长整数类型别名更好?
其次,本库的定长整数类型依赖了 <stdint.h>
。它是 C99/C++11 起的标准库头文件,即使 MSVC 也支持。
是否考虑在此方面移除对 _MSC_VER
的检测?
uint32_t next() {
static const uint32_t M = 2147483647L; // 2^31-1
static const uint64_t A = 16385; // 2^14+1
// Computing _seed * A % M.
uint64_t p = _seed * A;
_seed = static_cast<uint32_t>((p >> 31) + (p & M));
if (_seed > M) _seed -= M;
return _seed;
}
其中if (_seed > M) _seed -= M; 这行是不是多余的, 因为M本来就是uint32_t的最大值, 上面一行强转uint32_t之后不能大于M, if这条语句是不可能走到的
做了一个测试,发现对于double
类型转为字符串,速度超级慢
const size_t N = 10000000;
template<typename T>
void benchPrintf(const char* fmt) {
TimeStamp start = TimeStamp::now();
char buf[32];
for (size_t i = 0; i < N; ++i)
snprintf(buf, sizeof buf, fmt, (T)(i));
TimeStamp end = TimeStamp::now();
printf("benchPrintf %f\n", timeDifference(end, start));
}
template<typename T>
void benchStringStream() {
TimeStamp start = TimeStamp::now();
std::ostringstream os;
for (size_t i = 0; i < N; ++i) {
os << (T)(i);
os.seekp(0, std::ios_base::beg);
}
TimeStamp end = TimeStamp::now();
printf("benchStringStream %f\n", timeDifference(end, start));
}
template<typename T>
void benchStream() {
TimeStamp start = TimeStamp::now();
FStream os;
for (size_t i = 0; i < N; ++i) {
os << (T)(i);
os.clear();
}
TimeStamp end = TimeStamp::now();
printf("benchStream %f\n", timeDifference(end, start));
}
int main()
{
puts("int");
benchPrintf<int>("%d");
benchStringStream<int>();
benchStream<int>();
puts("double");
benchPrintf<double>("%.12g");
benchStringStream<double>();
benchStream<double>();
puts("int64_t");
benchPrintf<int64_t>("%" PRId64);
benchStringStream<int64_t>();
benchStream<int64_t>();
puts("void*");
benchPrintf<void*>("%p");
benchStringStream<void*>();
benchStream<void*>();
}
如题
FLOG << "This is FLOG (fatal).. " << 23;
执行这句的时候报错
0x00007FFFD0CCE91E (ucrtbase.dll) (**.exe 中)处有未经处理的异常: 请求了严重的程序退出。
想问下是什么情况导致的?
代码和设置没有做任何更改
目前看来这些代码并没有按照 C++11 前和 C++11 开始条件编译。假如这是有意的,那么我认为有些细节实现应当继续改进:
def.h
应当直接使用 <cstdint>
或者 <stdint.h>
。其他代码应该直接使用 (u)intN_t
以减少冲突。thread_local
代替 __thread
。<atomic>
。swap
函数和移动特殊成员函数应当加上 noexcept
。很多时候gflag已经成为标配了,能否支持让日志通过flag进行配置
只要我使用 co::sleep 函数就会报错
co 使用cmake 编译得 然后引入了 头文件 和LIB文件
使用官方的 client 代码示例
`
sock_t fd = co::tcp_socket();
struct sockaddr_in addr;
co::init_ip_addr(&addr, "127.0.0.1", 7788);
co::connect(fd, &addr, sizeof(addr), 3000);
co::set_tcp_nodelay(fd);
char buf[8] = { 0 };
for (int i = 0; i < 7; ++i) {
co::sleep(1000);
LOG << "send ping";
co::send(fd, "ping", 4);
co::recv(fd, buf, 4);
LOG << "recv " << buf;
}
co::close(fd);
`
co::connect 填写第4个参数会报错 崩溃
co::sleep 也会报错 崩溃
错误提示
Debug Assertion Failed!
Program: E:\fiber\exiecheng\coroutine\Debug\testdll.exe
File: D:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.26.28801\include\xtree
Line: 229
Expression: map/set iterators incompatible
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
error: co/impl/../../unix/thread.h:184:16: 错误:ambiguating new declaration of ‘__pid_t xxGettid()’
184 | #define gettid xxGettid
| ^~~~~~~~
co/impl/../../unix/thread.h:178:21: 附注:old declaration ‘unsigned int xxGettid()’
178 | inline unsigned int xxGettid() {
| ^~~~~~~~
I guess that a different program design will be needed for your function “on_signal".
I interpret the software situation in the way that the usage of the static variable “logger” might not fit to async-signal-safety.
当JSON字符串中含有1.0
之类的数值时,json::Value::str()
会将其序列化为1
,这与原来该字段的类型不符,如果多次依次执行序列化、反序列化操作,会导致断言。
版本:Commit 95535b3 之前都有此现象
系统:Debian 10(Windows未测试)
内核:5.4.0-1-amd64
示例
#include <stdio.h>
#include "base/json.h"
fastring s = "{\"value\": 12.0}";
int main(int argc, char** argv) {
auto j1 = json::parse(s);
auto j2 = json::parse(j1.str());
printf("j1 value: %f\n", j1["value"].get_double());
printf("j2 value: %f\n", j2["value"].get_double());
return 0;
}
执行结果
j1[0]: 12.000000
j_test: ./base/json.h:226: double json::Value::get_double() const: Assertion `this->is_double()' failed.
error: execv(/home/tiger/Codes/co/build/linux/x86_64/release/j_test) failed(-1)!
原因:序列化操作使用了fast::dtoa()
,而fast::dtoa()
在输出浮点时使用了Conversion Specifier g
,这会导致尾部的0
会被移除。这样就造成了类型不一致的问题。
@idealvin 你好。
按我的理解,当 thread_ptr
的对象,例如 foo
,以 std::ref(foo)
的方式传进线程函数之后,子线程是无法获取父线程设置的指针值的。也就是说,任何一个线程要使用 foo
,都必须现在线程内设置 foo
指向的对象才能使用。
既然如此,为什么不在每个线程里分别使用 std::unique_ptr
呢?使用 thread_ptr
的好处在哪里?
能否给个CMAKE的编译脚本,最好在alpine的环境下也能编译通过,github上很多库我在制作alpine镜像时候都碰到各种问题
真实个大牛牛
不错,这是一个好东西
有支持unicode的计划吗? 或其提供编码转换的类?
类似于文档的这种 日志输出的位置,日志文件名字,应该如何设置呢?
`//日志打印输出的位置
DEF_string(log_dir, "../log", "Log dir, will be created if not exists");
//日志文件名
DEF_string(log_file_name, "acl_log", "name of log file, using exename if empty");
//日志打印级别
DEF_int32(min_log_level, 0, "write logs at or above this level, 0-4 (debug|info|warning|error|fatal)");
//输出到终端
DEF_bool(cout, true, "also logging to terminal");
DEF_int32(co_sched_num, 100, "协程栈大小,每个调度线程都会分配一个栈,调度线程内的协程共用这个栈。");
DEF_int32(co_max_recv_size, 2, "一次能接收的最大数据长度,默认为 1M,超过此大小,分批接收。");
DEF_int32(co_max_send_size, 2, "一次能发送的最大数据长度,默认为 1M,超过此大小,分批发送");`
recursive decent其实还好……能通过这里的test case就够了。
哈哈拿 Asteria 跑了一下,跑出一堆 XPASS 出来。这里有几个 JSON5 的特性,但是都 Asteria 当扩展了。
Originally posted by @lhmouse in #4 (comment)
fastring
类的引用计数未使用原子对象。这显然会造成多线程同时修改时的数据竞争。希望作者注明这种设计是否有意的。fastring
类的内存分配、释放函数是不能替换的。我认为替换全局的 operator new
和 operator delete
是在一定应用条件下提高性能的做法,但 fastring
并不能从中受益。请问co中的mutex, thread等库在c++11和以后的标准库中都有对应的版本,它们的区别是什么?
我在开发的过程中应该如何选择?
If the fd
value greater than 1024
, this line would lead to overflow error:
// from base/co/impl/epoll.cc
int& x = _ev_map[fd];
你的是标准传统的实现. 大多数业务场景不要这么强的顺序和严格容量限制(稍微超一点),
我的实现 https://github.com/ktprime/emhash/blob/master/lru_size.h
只用一个数组, 乐观估计比你的快10倍(有空我测试一下).
for (int i = 0; i < 1000*10; i++)
{
go(client_fun);
}
https://github.com/idealvin/co/blob/110eadde2c89dffa259a161c100cd4161253441f/base/json.cc#L15
正常访问一个object
的member
时,应该先调用has_member()
来进行判断。但看上面函数的代码,如果直接使用[]
来访问相关member
,这里的逻辑似乎是打算支持这种行为?
如果不支持的话,21&22行的意义何在呢?
如果支持的话,接下来访问其它member
或者调用str()
就会出错了。如以下代码:
#include "co/json.h"
int main() {
auto v = json::parse("{\"name\": \"tiger\"}");
v["n"];
printf("%s\n", v["name"].str().c_str());
return 0;
}
输出结果是null
目前执行xmake install
后,会将头文件放在base
目录下,静态库被命名为libbase.a
。base
这个名字太普通了,不够将库与程序内部的名字区分开。既然项目名叫co
,何不将头文件放在include/co
目录下,且库名为libco.a
或libco.so
?
这个动静有点大,但从长远来看,我觉得有必要来执行这个改动。
希望能补充定时器的功能
inline void set_cloexec(sock_t fd) {
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_EXCL);
}
O_EXCL
or FD_CLOEXEC
?
如题, 即使不能全功能, 是否考虑在example中提供 go java 语言作为客户端的例子.
将co log编入dll,使用c#调用,.log文件中会缺失很多条log,并且会产生.fatal文件,.fatal文件事例如下:
1216 22:30:33] Error: Unrecognized Exception
D:\Project\co\base\stack_trace\StackWalker.cpp (1096): StackWalker::ShowCallstack
D:\Project\co\base\stack_trace\stack_trace_win.cpp (203): `anonymous namespace'::StackTraceImpl::on_exception
00007FFBA96B78D8 (ntdll): (filename not available): RtlInitializeCriticalSection
00007FFBA965D4FA (ntdll): (filename not available): RtlWalkFrameChain
00007FFBA965BE9A (ntdll): (filename not available): RtlRaiseException
00007FFBA671A388 (KERNELBASE): (filename not available): RaiseException
00007FFB54122413 (mono-2.0-bdwgc): (filename not available): mono_native_thread_set_name
00007FFB541D3B60 (mono-2.0-bdwgc): (filename not available): mono_thread_set_manage_callback
00007FFB541DC685 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541D57E8 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541D5576 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFBA8134034 (KERNEL32): (filename not available): BaseThreadInitThunk
00007FFBA96C3691 (ntdll): (filename not available): RtlUserThreadStart
1216 22:30:33] Error: Unrecognized Exception
D:\Project\co\base\stack_trace\StackWalker.cpp (1096): StackWalker::ShowCallstack
D:\Project\co\base\stack_trace\stack_trace_win.cpp (203): `anonymous namespace'::StackTraceImpl::on_exception
00007FFBA96B78D8 (ntdll): (filename not available): RtlInitializeCriticalSection
00007FFBA965D4FA (ntdll): (filename not available): RtlWalkFrameChain
00007FFBA965BE9A (ntdll): (filename not available): RtlRaiseException
00007FFBA671A388 (KERNELBASE): (filename not available): RaiseException
00007FFB54122413 (mono-2.0-bdwgc): (filename not available): mono_native_thread_set_name
00007FFB541D3B60 (mono-2.0-bdwgc): (filename not available): mono_thread_set_manage_callback
00007FFB541D8B0B (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541DB231 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541D57E8 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFB541D5576 (mono-2.0-bdwgc): (filename not available): mono_threads_set_shutting_down
00007FFBA8134034 (KERNEL32): (filename not available): BaseThreadInitThunk
00007FFBA96C3691 (ntdll): (filename not available): RtlUserThreadStart
I would like to point out that identifiers like “_Log
” and “__STACKWALKER_H__
” do eventually not fit to the expected naming convention of the C++ language standard.
Would you like to adjust your selection for unique names?
现版本的 fastring
拥有直接利用未被管理的内存的构造函数。看起来此构造函数得到使用的地方看起来很少(目前只注意到此处),而且写法上没有体现原位构造的特征。
我个人认为把它改成 static 成员函数(如 fastring::from_raw_buffer
)或者友元自由函数(如 friend raw_buffer_to_fastring
)会让用户更谨慎而安全地使用。
另外,或许只把此功能作为内部实现而非作为公开 API 也是一种选择。
recv(sock_t fd, void* buf, int n, int ms)超时后程序崩溃
比如实现http下载网页或文件
谢谢!
环境:vs2019
问题:运行rpc test程序时出现错误map/set iterators incompatible
我根据文档上的xmake编译步骤,编译co/unitest时报错
checking for the architecture ... x64
checking for the Microsoft Visual Studio (x64) version ... 2017
error: unknown target(base) for unitest.deps!
该如何解决
vs2015那个文件夹的sln编译不过。
我尝试删除一些依赖,但是因为context文件夹下有一些汇编文件不带明白,不敢乱动。
co::close 触发了del_event(ev)
但是co::recvfrom等待的EV_read 消息订阅被删除,但是recvfrom仍然在等待。
解决方法:
1、或许可以加入EV_close/EV_ignore之类的事件。
2、IoEvent加入多事件绑定,同时绑定EV_read和EV_close/EV_ignore。
string没有实现\uxxxx
形式的unicode转义,以及\b
\f
的转义。
看实现实在没法看出来为什么会比rapidJSON
性能高,而rapidJSON
甚至都用上了SIMD优化,麻烦给出benchmark?
The implementation of fastring
is not thread-safe. That’s fine, but people might get in trouble if they don’t know this, since std::string is thread-safe. So it would be good to point this out in the documentation.
(Making fastring
thread safe is probably not a good idea. I’ve read that std::string
used to use ref-counting and copy-on-write the way yours does, but the atomic operations or mutexes needed to make it thread-safe hurt performance a lot, and it’s actually faster for it to always copy.)
插入发现存在是不是调整一下位置到头部?
list用了2个使用一个效率会更好一点?
//一般插入实现大致这样
void put(const Key& key,const Value& value){
const auto iter = _cache.find(key);
if(iter!= _cache.end()){
// 找到了就更新value,并提取到最前面
iter->second->value = value;
//move iter->second to _keys' begin postion
_keys.splice(_keys.begin(),_keys,iter->second);
return;
}
_keys.emplace_front(key,value);
_cache[key] = _keys.begin();
resize();
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.