- 浏览: 164282 次
- 性别:
- 来自: 保山腾冲
-
文章分类
最新评论
-
TNTDoctor:
谢谢,标记一下,有空来看看
(转)Haskell与范畴论 -
t173625478:
文章一般般,不够透彻,以至于误解了很多函数式特性的由来和作用。 ...
(转)函数式编程另类指南 -
liyiwen007:
学习了!
很受益!
用AGG实现高质量图形输出(二) -
hqs7636:
感谢!!!!!!!
《learn to tango with D》译文 -
rocex:
多谢,刚好用到。
《learn to tango with D》译文
Ownership hierarchy using owner::this
In my last post I talked about the proposal for the ownership scheme for multithreaded programs that provides alias control and eliminates data races. The scheme requires the addition of new type qualifiers to the (hypothetical) language. The standard concern is that new type qualifiers introduce code duplication. The classic example is the duplication of getters required by the introduction of the const modifier:
class Foo { private Bar _bar; public: Bar get() { return _bar; } const Bar get() const { return _bar; } }
Do ownership annotations lead to the same kind of duplication? Fortunately not. It’s true that, in most cases, two implementations of each public method are needed–with and without synchronization–but this is taken care by the compiler, not by the programmer. Unlike in Java, we don’t need a different class for shared Vector and thread-local ArrayList. In my scheme, when a vector is instantiated as a monitor (shared), the compiler automatically puts in the necessary synchronization code.
Need for generic code
The ownership scheme introduces an element of genericity by letting the programmer specify ownership during the instantiation of a class (just as a template parameter is specified during the instantiation of a template).
I already mentioned that most declarations can be expressed in two ways: one using type qualifiers, another using template notation–the latter exposing the generic nature of ownership annotations. For instance, these two forms are equivalent:
auto foo2 = new shared Foo; auto foo2 = new Foo<owner::self>;
The template form emphasizes the generic nature of ownership annotations.
With the ownership system in place, regular templates parametrized by types also gain an additional degree of genericity since their parameters now include implicit ownership information. This is best seen in objects that don’t own the objects they hold. Most containers have this property (unless they are restricted to storing value types). For instance, a stack object might be thread-local while its elements are either thread-local or shared. Or the stack might be shared, with shared elements, etc. The source code to implement such stacks may be identical.
The polymorphic scheme and the examples are based on the GRFJ paper I discussed in a past post.
An example
- Stack
A parameterized stack might look like this :
class Stack<T> { private Node<T> _top; public: void push(T value) { auto newNode = new Node<owner::this, T>; newNode.init(:=value, _top); _top = newNode; } T pop() { if (_top is null) return null; auto value := _top.value(); _top = _top.next(); return value; } }
This stack is parametrized by the type T. This time, however, T includes ownership information. In particular T could be shared, unique, immutable or–the default–thread-local. The template picks up whatever qualifier is specified during instantiation, as in:
auto stack = new Stack<unique Foo>;
The _top (the head of the linked list) is of the type Node, which is parametrized by the type T. What is implicit in this declaration is that _top is owned by this–the default assignment of ownership for subobjects. If you want, you can make this more explicit:
private Node<owner::this, T> _top;
Notice that, when constructing a new Node, I had to specify the owner explicitly as this. The default would be thread-local and could leak thread-local aliases in the constructor. It is technically possible that the owner::this could, at least in this case, be inferred by the compiler through simple flow analysis.
Let’s have a closer look at the method push, where some interesting things are happening. First push creates a new node, which is later assigned to _top. The compiler cannot be sure that the Node constructor or the init method don’t leak aliases. That looks bad at first glance because, if an alias to newNode were leaked, that would lead to the leakage of _top as well (after a pop).
And here’s the clincher: Because newNode was declared with the correct owner–the stack itself–it can’t leak an alias that has a different owner. So anybody who tries to access the (correctly typed) leaked alias would have to hold the lock on the stack. Which means that, if the stack is shared, unsynchronized access to any of the nodes and their aliases is impossible. Which means no races on Nodes.
I also used the move operator := to move the values stored on the stack. That will make the stack usable with unique types. (For non-unique types, the move operator turns into regular assignment.)
I can now instantiate various stacks with different combinations of ownerships. The simplest one is:
auto localStack = new Stack<Foo>;
which is thread-local and stores thread-local objects of class Foo. There are no restrictions on Foo.
A more interesting combination is:
auto localStackOfMonitors = new Stack<shared Foo>;
This is a thread-local stack which stores monitor objects (the opposite is illegal though, as I’ll explain in a moment).
There is also a primitive multithreaded message queue:
auto msgQueue = new shared Stack<shared Foo>;
Notice that code that would try to push a thread-local object on the localStackOfMonitors or the msgQueue would not compile. We need the rich type system to be able to express such subtleties.
Other interesting combinations are:
auto stackOfImmutable = new shared Stack<immutable Foo>; auto stackOfUnique = new shared Stack<unique Foo>;
The latter is possible because I used move operators in the body of Stack.
- Node
Now I’ll show you the fully parameterized definition of Node. I made all ownership annotations explicit for explanatory purposes. Later I’ll argue later that all of them could be elided.
class Node<T> { private: T _value; Node<owner::of_this, T> _next; public: void init(T v, Node<owner::of_this, T> next) { _value := v; _next = next; } T value() { return :=_value; } Node<owner::of_this, T> next() { return _next; } }
Notice the declaration of _next: I specified that it must be owned by the owner of the current object, owner::of_this. In our case, the current object is a node and its owner is an instance of the Stack (let’s assume it’s the self-owned msgQueue).
This is the most logical assignment of ownership: all nodes are owned by the same stack object. That means no ownership conversions need be done, for instance, in the implementation of pop. In this assignment:
_top = _top.next();
the owner of _top is msgQueue, and so is the owner of its _next object. The types match exactly. I drew the ownership tree below. The fat arrows point at owners.
But that’s not the only possibility. The default–that is _next being owned by the current node–would work too. The corresponding ownership tree is shown below.
The left-hand side of the assignment
_top = _top.next();
is still owned by msgQueue. But the _next object inside the _top is not. It is owned by the _top node itself. These are two different owners so, during the assignment, the compiler has to do an implicit ownership conversion. Such conversion is only safe if both owners belong to the same ownership tree (sometimes called a “region”). Indeed, ownership is only needed for correct locking, and the locks always reside at the top of the tree (msgQueue in this case). So, after all, we don’t need to annotate _next with the ownership qualifier.
The two other annotations can be inferred by the compiler (there are some elements of type inference even in C++0x and D). The argument next to the method init must be either owned by this or be convertible to owner::this because of the assignment
_next = next;
Similarly, the return from the method next is implicitly owned by this (the node). When it’s used in Stack.pop:
_top = _top.next();
the owner conversion is performed.
With ownership inference, the definition of Node simplifies to the following:
class Node<T> { private: T _value; Node<T> _next; // by default owned by this public: void init(T v, Node<T> next) { _value := v; _next = next; // inference: owner of next must be this } T value() { return :=_value; } Node<T> next() { return _next; // inference: returned node is owned by this } }
which has no ownership annotations.
Let me stress again a very important point: If init wanted to leak the alias to next, it would have to assign it to a variable of the type Node<owner::this, T>, where this is the current node. The compiler would make sure that such a variable is accessed only by code that locks the root of the ownership tree, msgQueue. This arrangement ensures the absence of races for the nodes of the list.
Another important point is that Node contains _value of type T as a subobject. The compiler will refuse instantiations where Node’s ownership tree is shared (its root is is self-owned), and T is thread-local. Indeed, such instantiation would lead to races if an alias to _value escaped from Node. Such an alias, being thread-local, would be accessible without locking.
Comment on notation
In general, a template parameter list might contain a mixture of types, type qualifiers, values, (and, in D, aliases). Because of this mixture, I’m using special syntax for ownership qualifiers, owner::x to distinguish them from other kinds of parameters.
As you have seen, a naked ownership qualifier may be specified during instantiation. If it’s the first template argument, it becomes the owner of the object. Class templates don’t specify this parameter, but they have access to it as owner::of_this.
Other uses of qualifier polymorphism
Once qualifier polymorphism is in the language, there is no reason not to allow other qualifiers to take part in polymorphism. For instance, the old problem of having to write separate const versions of accessors can be easily solved:
class Foo { private Bar _bar; public mut_q Bar get<mutability::mut_q>() mut_q { return _bar; } }
Here method get is parametrized by the mutability qualifier mut_q. The values it can take are: mutable (the default), const, or immutable. For instance, in
auto immFoo = new immutable Foo; immutable Bar b = immFoo.get();
the immutable version of get is called. Similarly, in
void f(const Foo foo) { const Bar b = foo.get(); }
the const version is called (notice that f may also be called with an immutable object–it will work just fine).
Class methods in Java or D are by default virtual. This is why, in general, non-final class methods cannot be templatized (an infinite number of possible versions of a method would have to be included in the vtable). Type qualifiers are an exception, because there is a finite number of them. It would be okay for the vtable to have three entries for the method get, one for each possible value of the mutability parameter. In this case, however, all three are identical, so the compiler will generate just one entry.
Conclusion
The hard part–explaining the theory and the details of the ownership scheme–is over. I will now switch to a tutorial-style presentation that is much more programmer friendly. You’ll see how simple the scheme really is in practice.
发表评论
-
haskell趣学指南(链接)
2010-05-16 16:25 920http://fleurer-lee.com/lyah/ 一 ... -
Parallel Programming with Hints(转)
2010-05-14 12:27 934Parallel Programming with Hint ... -
Linguaggio D versione 2(转)
2010-03-31 06:42 931Linguaggio D versione 2 转自http ... -
The Case for D —硬币的另一面
2009-06-20 11:35 1303The Case for D —硬币的另一面 作者:leon ... -
The Case for D - the other side of the coin
2009-06-19 12:27 1045The Case for D - the other side ... -
如何手写语法分析器
2009-04-01 15:51 1432如何手写语法分析器 http://www.cppblog.c ... -
学习一种新的编程语言所要做的15个练习
2009-01-29 23:30 865学习一种新的编程语言 ...
相关推荐
chgrp (Change group ownership of file(s))** `chgrp` 命令用于更改一个或多个文件或目录的组所有权。这对于需要更改文件访问权限的情况非常有用。 **4. chmod (Change file mode bits)** `chmod` 命令用于更改...
包括:源程序工程文件、Proteus仿真工程文件、配套技术手册等 1、采用51/52单片机作为主控芯片; 2、采用1602液晶显示; 3、采用5*8矩阵键盘输入; 4、功能键包括:复位键(RST),回删键(DEL),确定键(OK),第二功能切换(2U),背光灯键(LED); 5、运算均为单精度浮点数,包括: 加(+),减(-),乘(x),除(÷), e底指数(e^n),N次方(x^n),开N次方(sqrt), 正弦(sin),余弦(cos),正切(tan), 对数(log), 阶乘(n!)(n<35), 排列(Arn), 累加(∑), *开启第二功能(2U)后可用: 反正弦(asin),反余弦(acos),反正切(atan), 组合(Crn)
内容概要:本文详细介绍了如何利用三菱FX2N系列PLC构建机械手控制系统。主要内容涵盖电路图设计、IO表配置、源程序编写以及单机组态。文中提供了具体的梯形图编程实例,展示了如何通过PLC精确控制机械手的各种动作,如抓取、移动和放置。此外,还分享了许多实用的调试技巧和注意事项,强调了传感器状态交叉验证和关键动作的时间守护机制。通过这些内容,读者可以全面了解PLC在机械手控制中的应用。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程和机械手控制感兴趣的初学者和有一定经验的研发人员。 使用场景及目标:适用于需要设计和实施机械手控制系统的工业场合,帮助工程师掌握PLC编程技巧,提高机械手控制系统的稳定性和可靠性。 其他说明:文章不仅提供理论指导,还包括大量实战代码和调试经验,有助于读者快速上手并在实践中不断优化系统性能。
内容概要:本文档提供了用于生成具有时尚性感元素的美女跳舞图像的提示词指南。文档内容包括角色设定为擅长描绘时尚与超现实主义图片的创作者,背景设定强调女性形象,偏好展现性感漂亮女孩的镜头表达。目标在于根据用户指令创作三幅统一风格的图像,注重色彩搭配和高清效果,同时确保每张图片都具备半身像、真实感和电影效果的特点。文档还给出了具体的输出示例,详细描述了人物形象、服装搭配以及场景布置等要素,旨在为用户提供满意的图像生成服务。; 适合人群:对图像生成感兴趣,尤其是喜欢带有时尚性感元素的美女图像的用户。; 使用场景及目标:①根据用户提供的简单场景信息(如户外或室内)生成三幅不同场景但风格统一的赛博朋克风格美女跳舞图像;②确保生成的图像符合特定的要求,如半身像、真实感、电影效果、性感服装、特定灯光效果等;③通过询问用户对生成图像的满意度来保证服务质量。; 其他说明:文档明确了图像生成的工作流程,从接收用户指令到根据反馈调整生成内容,确保整个过程高效且满足用户需求。同时,文档还限制了生成图像的具体条件,如场景必须为赛博朋克风格、不能出现鞋子和其他人等,以保证图像的独特性和一致性。
题目描述 1.问题描述 一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的 数,例如1135是一个数位递增的数,而1024不是一个数位递增的数。 给定正整数n,请问在整数1至n中有多少个数位递增的数? 输入格式 输入的第一行包含一个整数n。 输出格式 输出一行包含一个整数,表示答案。 样例输入 30 样例输出
内容概要:本文详细介绍了基于非对称纳什谈判的多微网电能共享运行优化策略及其MATLAB代码实现。首先阐述了纳什谈判和合作博弈的基本理论,然后将多微网电能共享合作运行模型分解为微网联盟效益最大化和合作收益分配两个子问题。文中展示了如何通过交替方向乘子法(ADMM)进行分布式求解,确保各微网隐私安全。此外,还探讨了电转气(P2G)和碳捕集(CCS)设备的应用,以实现低碳调度。最后,通过具体代码示例解释了模型的构建、求解及优化过程。 适合人群:对电力系统优化、博弈论、MATLAB编程感兴趣的科研人员和技术开发者。 使用场景及目标:适用于希望深入了解多微网电能共享优化策略的研究者,旨在提高微网联盟的整体效益并实现公平合理的收益分配。同时,该策略有助于降低碳排放,提升系统的环境友好性和经济性。 其他说明:文章提供了详细的代码注释和调试技巧,帮助读者更好地理解和实现这一复杂的优化策略。
内容概要:本文详细介绍了如何利用MATLAB进行六轴机械臂的视觉控制系统仿真。首先,通过MATLAB的图像处理工具箱捕捉并处理实时视频流,使用HSV颜色空间进行颜色阈值处理,从而定位红色小球的位置。然后,借助Robotics Toolbox中的逆运动学模块,将摄像头获取的目标位置转换为机械臂的关节角度,确保机械臂能够精准地追踪目标。此外,还讨论了路径规划的方法,如使用五次多项式插值和平滑滤波器,使机械臂的动作更加流畅。文中强调了实际应用中可能遇到的问题及其解决方法,如奇异点处理、坐标系转换和机械臂的速度限制等。 适合人群:具有一定编程基础和技术背景的研究人员、工程师以及对机器人视觉控制感兴趣的开发者。 使用场景及目标:适用于希望在MATLAB环境中快速搭建和测试机械臂视觉控制系统的科研人员和工程师。主要目标是掌握从图像处理到机械臂控制的完整流程,理解各模块的工作原理,并能够在实际项目中应用。 其他说明:本文不仅提供了详细的代码示例,还分享了许多实用的经验和技巧,帮助读者更好地理解和优化仿真系统。同时提醒读者注意仿真与现实之间的差异,如摄像头延迟、机械臂传动误差等问题。
KUKA机器人相关文档
KUKA机器人相关文档
内容概要:本文详细介绍了三相变流器的模型预测控制(MPC)在Matlab/Simulink环境下的实现过程。首先,初始化程序设置了关键参数,如直流母线电压、开关频率和控制周期等,确保系统的稳定性和效率。接着,通过MPC_sfun.c实现了核心控制算法,采用状态空间模型进行滚动预测,提高了系统的动态响应能力。最后,利用out.m生成高质量的仿真结果图,展示了负载突变时的快速恢复特性,并提供了优化建议,如调整代价函数权重和引入软约束等。 适合人群:电力电子工程师、控制系统研究人员以及对MPC感兴趣的科研工作者。 使用场景及目标:适用于需要精确控制电压电流的场合,如电动汽车充电站、风力发电系统等。主要目标是提高系统的动态响应速度、降低总谐波失真(THD),并在性能和计算负担之间取得平衡。 其他说明:文中提到了一些实用技巧,如控制周期的选择、预测步长的优化、图形绘制的最佳实践等,有助于读者更好地理解和应用MPC控制策略。同时,强调了在实际应用中需要注意的问题,如避免过高开关频率导致器件损坏等。
网络炒作策划要点解析.ppt
内容概要:本文详细介绍了三菱Q03UDE PLC使用SFC(顺序功能图)编程方法在16轴伺服控制系统中的应用。文章首先概述了硬件配置,包括500个IO点、16轴伺服控制以及触摸屏的画面编程。接着深入探讨了SFC编程的具体实现方式,如将复杂的轴控制分解为独立的流程块,利用并行结构解决多轴同步问题,通过触摸屏实时监控和反馈SFC步状态,以及如何高效管理和复用输出点。此外,文章还讨论了SFC在状态管理和报警处理方面的优势,并提供了具体的代码示例来展示其实现细节。最后,作者分享了一些实用技巧和注意事项,强调了SFC编程相比传统梯形图的优势。 适合人群:从事工业自动化控制系统的工程师和技术人员,尤其是对三菱PLC和SFC编程感兴趣的读者。 使用场景及目标:适用于需要进行复杂多轴伺服控制项目的工程师,旨在提高调试效率、减少信号冲突、缩短新人培养周期,并提供一种更加直观和高效的编程方法。 其他说明:文中提到的实际项目经验有助于读者更好地理解和应用SFC编程技术,同时也提醒了一些常见的错误和陷阱,帮助读者避免不必要的麻烦。
内容概要:本文详细介绍了如何使用LabVIEW实现与三菱FX3U PLC的串口通讯,采用Modbus无协议通讯方式进行简单读写操作。主要内容包括PLC通讯参数配置、LabVIEW工程结构搭建、Modbus报文构造方法以及具体的读写数据模块实现。文中提供了详细的代码示例和注意事项,帮助读者快速理解和实践这一通讯过程。 适合人群:对工业自动化有一定兴趣的技术人员,尤其是熟悉LabVIEW和三菱PLC的工程师。 使用场景及目标:适用于需要将LabVIEW作为上位机与三菱FX3U PLC进行串口通讯的应用场合,如工业控制系统、实验教学等。主要目标是掌握Modbus协议的基础知识及其在LabVIEW中的具体实现。 其他说明:文章还提供了一些常见的错误排查方法和实用技巧,如CRC校验的处理、地址偏移量的注意事项等。此外,附带了完整的源码供读者下载和参考。
图像检索_基于零样本开集的草图图像检索系统实现_附项目源码+流程教程_优质项目实战
基于C语言写的电话簿程序
包括:源程序工程文件、Proteus仿真工程文件、配套技术手册等 1、采用51单片机作为主控芯片; 2、采用1602液晶显示检测电压值,范围0~20V; 3、采用ADC0808进行模数转换;
内容概要:本文介绍了一个专业的剧本杀创作作家AI。它能根据客户需求创作各种风格和难度的剧本杀剧本,并提供创作建议和修改意见。其目标是创造引人入胜、逻辑严密的剧本体验。它的工作流程包括接收理解剧本要求、创作剧本框架情节、设计角色背景线索任务剧情走向、提供修改完善建议、确保剧本可玩性和故事连贯性。它需保证剧本原创、符合道德法律标准并在规定时间内完成创作。它具备剧本创作技巧、角色构建理解、线索悬念编织、文学知识和创意思维、不同文化背景下剧本风格掌握以及剧本杀游戏机制和玩家心理熟悉等技能。; 适合人群:有剧本杀创作需求的人群,如剧本杀爱好者、创作者等。; 使用场景及目标:①为用户提供符合要求的剧本杀剧本创作服务;②帮助用户完善剧本杀剧本,提高剧本质量。; 阅读建议:此资源详细介绍了剧本杀创作作家AI的功能和服务流程,用户可以依据自身需求与该AI合作,明确表达自己的创作需求并配合其工作流程。
内容概要:本文详细介绍了如何利用Matlab进行静态图片的美颜和特效处理。首先通过Viola-Jones算法进行人脸定位,然后采用双边滤波对皮肤进行磨皮处理,在HSV色彩空间中调整亮度以达到美白效果,最后运用小波变换将星空图等特效融合到图片中。整个过程中涉及多个图像处理技术和算法,如Haar特征、双边滤波、HSV转换、小波变换等。 适合人群:对图像处理感兴趣的初学者以及有一定Matlab基础的研发人员。 使用场景及目标:适用于希望深入了解图像处理原理并掌握具体实现方法的学习者;目标是能够独立完成简单的图像美化任务,如人像磨皮、美白、特效添加等。 其他说明:文中提供了完整的代码示例,帮助读者更好地理解和实践相关技术。同时强调了参数选择的重要性,并给出了合理的建议范围。
KUKA机器人相关文档
内容概要:本文详细介绍了在无电子凸轮功能情况下,利用三菱FX3U系列PLC和威纶通触摸屏实现分切机上下收放卷张力控制的方法。主要内容涵盖硬件连接、程序框架设计、张力检测与读取、PID控制逻辑以及触摸屏交互界面的设计。文中通过具体代码示例展示了如何初始化寄存器、读取张力传感器数据、计算张力偏差并实施PID控制,最终实现稳定的张力控制。此外,还讨论了卷径计算、速度同步控制等关键技术点,并提供了现场调试经验和优化建议。 适合人群:从事自动化生产设备维护和技术支持的专业人士,尤其是熟悉PLC编程和触摸屏应用的技术人员。 使用场景及目标:适用于需要对分切机进行升级改造的企业,旨在提高分切机的张力控制精度,确保材料切割质量,降低生产成本。通过本方案可以实现±3%的张力控制精度,满足基本生产需求。 其他说明:本文不仅提供详细的程序代码和硬件配置指南,还分享了许多实用的调试技巧和经验,帮助技术人员更好地理解和应用相关技术。