GVKun编程网logo

ReactOS 源码分析 (二) By:ProgrammeBoy(react源码深度解析 慕课网)

15

在本文中,我们将带你了解ReactOS源码分析(二)By:ProgrammeBoy在这篇文章中,我们将为您详细介绍ReactOS源码分析(二)By:ProgrammeBoy的方方面面,并解答react

在本文中,我们将带你了解ReactOS 源码分析 (二) By:ProgrammeBoy在这篇文章中,我们将为您详细介绍ReactOS 源码分析 (二) By:ProgrammeBoy的方方面面,并解答react源码深度解析 慕课网常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的.Net中的反应式编程(Reactive Programming)、8 Traits of an Experienced Programmer that every beginner programmer should know、Cg Programming/ProgrammableGraphics Pipeline、com.facebook.react.views.progressbar.ReactProgressBarViewManager的实例源码

本文目录一览:

ReactOS 源码分析 (二) By:ProgrammeBoy(react源码深度解析 慕课网)

ReactOS 源码分析 (二) By:ProgrammeBoy(react源码深度解析 慕课网)

重头戏FreeLdr.sys

简单介绍

代码位置: D:/ReactOS/ReactOS_src/boot/freeldr/freeldr/

先说下freeldr.sys,这个东东包含了内存管理、文件系统、缓存、UI、磁盘管理等要要的操作系统的功能。再加上点进程管理就可以成一个小操作系统了。那好我们就分析下freeldr以便我们能更好的理解操作系统。

来到代码目录下,好多代码,代码的入口函数在那个文件呀,怎么找呀。我啰嗦下,但不知道对不对,我们代开D:/ReactOS/ReactOS_src/boot/freeldr/freeldr.rbuild文件

像这样:

<?xml version="1.0"?>

<!DOCTYPE group SYstem "../../tools/rbuild/project.dtd">

<group xmlns:xi="http://www.w3.org/2001/XInclude">

<directory name="bootsect">

<xi:include href="bootsect/bootsect.rbuild" />

</directory>

<directory name="freeldr">

<xi:include href="freeldr/freeldr_startup.rbuild" />

<xi:include href="freeldr/freeldr_base64k.rbuild" />

<xi:include href="freeldr/freeldr_base.rbuild" />

<xi:include href="freeldr/freeldr_arch.rbuild" />

<xi:include href="freeldr/freeldr_main.rbuild" />

<xi:include href="freeldr/setupldr_main.rbuild" />

<xi:include href="freeldr/freeldr.rbuild" />

<xi:include href="freeldr/setupldr.rbuild" />

</directory>

<directory name="fdebug">

<xi:include href="fdebug/fdebug.rbuild" />

</directory>

</group>

看第一个是什么呀?对呀是: freeldr/freeldr_startup.rbuild,那就去子目录找下,找到了,内容如下:

<?xml version="1.0"?>

<!DOCTYPE module SYstem "../../../tools/rbuild/project.dtd">

<module name="freeldr_startup" type="objectlibrary">

<include base="freeldr_startup">include</include>

<include base="ntoskrnl">include</include>

<compilerflag>-fno-inline</compilerflag>

<compilerflag>-fno-zero-initialized-in-bss</compilerflag>

<directory name="arch">

<if property="ARCH" value="i386">

<directory name="i386">

<file first="true">fathelp.asm</file>

<file>arch.S</file>

</directory>

</if>

<if property="ARCH" value="amd64">

<directory name="amd64">

<file first="true">fathelp.S</file>

<file>arch.S</file>

</directory>

</if>

</directory>

</module>

前面已经假定我们的机器是i386的了,看到带颜色的那几句吗?尤其是蓝色那句,好像是第一个程序源码的第一个文件到底是不是呢?我用IDA看了下freeldr的反汇编确实是.就是那个fathelp.asm,那好我们来看下fathelp.asm..

Fathelp.asm

代码路径: D:/ReactOS/ReactOS_src/boot/freeldr/freeldr/arch/i386/fathelp.asm

看到代码

; This code will be stored in the first 512 bytes

; of freeldr.sys. The first 3 bytes will be a jmp

; instruction to skip past the FAT helper code

; that is stored in the rest of the 512 bytes.

;

; This code is loaded at 0000:8000 so we have to

; encode a jmp instruction to jump to 0000:8200

global _mainCRTStartup ; For Mingw32 builds where the linker looks for this symbol

_mainCRTStartup:

global start

start:

db 0xe9

db 0xfd

db 0x01

.以下省略

看到这我就不分析下面的啦,正如上面的注释所说,这个代码储存在freeldr.sys的前512字节中,3个字节会跳过这段代码,剩下的部分放在接下来的剩余空间内,这里为什么跳1fa?对呀,因为e9 01fd自身就3字节,加起来这好是0x200h,512字节.

arch.s

那好我们看下一个文件,下一个文件是什么了?怎么看?不会这么快就忘了吧,freeldr_startup.rbuild里呀!马上看下,哦是”arch.S”,?*.s是什么文件呢?不知道?我也不知道.google...知道了,原来也是汇编格式呀,只不过是AT&T汇编格式,和我们的nasm差不多,就是源/目的操作数的位置颠倒了下,这里我就不多说这个汇编的语法了,毕竟我们是分析代码嘛,大家可以去网上search,大有文章在.

看代码:

.text

.code16

/*支持C语言的注释和宏定义还有include,不错不错找个时间好好看下这个汇编*/

#define ASM

#include <arch.h>

#include <multiboot.h>

/*入口点*/

EXTERN(RealEntryPoint)

/*关中断*/

cli

/*寄存器初始化*/

xorw %ax,%ax

movw %ax,%ds

movw %ax,%es

movw %ax,%fs

movw %ax,%gs

movw %ax,%ss

/* Setup a stack */

movw stack16,%sp

sti

/* 进入保护模式,这是个重点,,一起去看这个函数的具体实现过程*/

call switch_to_prot

/*现在我们在保护模式下*/

.code32

/* 设置全局变量以后在freeldr.sys的其他地方会用着,先记着 */

xorl %eax,%eax

movl %eax,(_BootDrive)

movl %eax,(_BootPartition)

/* Store the boot drive */

movb %dl,(_BootDrive)

/* Store the boot partition */

movb %dh,(_BootPartition)

/* GO! */

/* 这里知道这个_BootMain是什么函数吗?freeldr.sys的一个用C写的函数在

*D:/ReactOS/ReactOS_src/boot/freeldr/freeldr/freeldr.c

*,这也说明我们的汇编要over

* 还有呀大家知道函数调用时一个字都不能错,但是但freeldr.c里定义的是BootMain,这里怎么多了个_(下横杠),

* 不会出错?原来这是使用C语言的__cdecl调用方式,MSDN中说 Underscore character (_) is prefixed to names

* 就是说在编译的时候会用_来修改函数名称,所以这里用了_BootMain切记,其他方式大家查MSDN

pushl %eax

call _BootMain

/* 再次转换到实模式*/

call switch_to_real

.code16

/* int 0x19是干嘛用的呀*/

/* INT19H是怎么处理启动的?
INT
19会将MBR512字节装载到内存0x7c00中,然后JUMP0x7c00处,开始执行MBR的可执行程序(masterbooter),Masterbooter最起码需要做这些事情:
*/

int $0x19

/* We should never get here */

stop:

jmp stop

nop

nop

/*

* Switches the processor to protected mode

* 转换处理器到保护模式

* it destroys eax

* 这里注意下,会改变eax中的内容

*/

EXTERN(switch_to_prot)

.code16

cli /* None of these */

/* We don't kNow what values are currently */

/*我不并不知道下面这些寄存器现在的值是多少*/

/* in the segment registers. So we are */

/* 所以现在我们重新加载这些值**/

/* going to reload them with sane values. */

/* Of course CS has to already be valid. */

/* 当然CS已经是被设置好的了*/

/* We are currently in real-mode so we */

/* 我们现在还在实模式下所以我们呢需要实模式的段值*/

/* need real-mode segment values. */

xorw %ax,%ss

/* Get the return address off the stack */

/*保存要返回的地址*/

popw (code32ret)

/* Save 16-bit stack pointer */

movw %sp,stack16

/* 这里必须懂得保护模式和实模式*/

/* 加载GDT */

lgdt gdtptr

/* 加载 IDT */

lidt i386idtptr

/*修改cr0寄存器,来开启保护模式状态 */

mov %cr0,%eax

orl $CR0_PE_SET,%eax

mov %eax,%cr0

/* Clear prefetch queue & correct CS */

ljmp $PMODE_CS,$inpmode

/* 进入32位程序段*/

.code32

inpmode:

/* Setup segment selectors */

movw $PMODE_DS,%ss

movl stack32,%esp

/* Put the return address back onto the stack */

/*将返回地址压入堆栈*/

pushl (code32ret)

/* Now return in p-mode! */

/* 返回主函数,我们现在是在保护模式下了*/

ret

/*

* Switches the processor back to real mode

* it destroys eax

*/

EXTERN(switch_to_real)

.code32

/* We don't kNow what values are currently */

/* in the segment registers. So we are */

/* going to reload them with sane values. */

/* Of course CS has to already be valid. */

/* We are currently in protected-mode so we */

/* need protected-mode segment values. */

movw $PMODE_DS,%ss

/* Get the return address off the stack */

popl (code16ret)

/* Save 32-bit stack pointer */

movl %esp,stack32

/* jmp to 16-bit segment to set the limit correctly */

ljmp $RMODE_CS,$switch_to_real16

switch_to_real16:

.code16

/* Restore segment registers to correct limit */

movw $RMODE_DS,%ss

/* 关闭保护模式 */

mov %cr0,%eax

andl $CR0_PE_CLR,%cr0

/* Clear prefetch queue & correct CS */

ljmp $0,$inrmode

inrmode:

movw %cs,%ss

/* Clear out the high 16-bits of ESP */

/* This is needed because I have one */

/* machine that hangs when booted to dos if */

/* anything other than 0x0000 is in the high */

/* 16-bits of ESP. Even though real-mode */

/* code should only use SP and not ESP. */

xorl %esp,%esp

movw stack16,%sp

/* Put the return address back onto the stack */

pushw (code16ret)

/* Load IDTR with real mode value */

lidt rmode_idtptr

sti /* These are ok Now */

/* Now return in r-mode! */

ret

/*

* Needed for enabling the a20 address line

*/

.code16

empty_8042:

.word 0x00eb,0x00eb // jmp $+2,jmp $+2

inb $0x64,%al

cmp $0xff,%al // legacy-free machine without keyboard

jz empty_8042_ret // controllers on Intel Macs read back 0xFF

testb $0x02,%al

jnz empty_8042

empty_8042_ret:

ret

/*下面的两个函数根本就没用到过*/

/*

* Enable the A20 address line (to allow access to over 1mb)

*/

EXTERN(_EnableA20)

.code32

pushal

call switch_to_real

.code16

call empty_8042

movb $0xD1,%al // command write

outb %al,$0x64

call empty_8042

mov $0xDF,%al // A20 on

out %al,$0x60

call empty_8042

call switch_to_prot

.code32

popal

ret

/*

* disable the A20 address line

*/

EXTERN(_disableA20)

.code32

pushal

call switch_to_real

.code16

call empty_8042

movb $0xD1,$0x64

call empty_8042

mov $0xDD,%al // A20 off

out %al,$0x60

call empty_8042

call switch_to_prot

.code32

popal

ret

..

.code32

/* 16-bit stack pointer */

stack16:

.word STACK16ADDR

/* 32-bit stack pointer */

stack32:

.long STACK32ADDR

/* 16-bit return address */

code16ret:

.long 0

/* 32-bit return address */

code32ret:

.long 0

.p2align 2 /* force 4-byte alignment */

gdt:

/* NULL Descriptor */

.word 0x0000

.word 0x0000

.word 0x0000

.word 0x0000

/* 32-bit flat CS */

.word 0xFFFF

.word 0x0000

.word 0x9A00

.word 0x00CF

/* 32-bit flat DS */

.word 0xFFFF

.word 0x0000

.word 0x9200

.word 0x00CF

/* 16-bit real mode CS */

.word 0xFFFF

.word 0x0000

.word 0x9E00

.word 0x0000

/* 16-bit real mode DS */

.word 0xFFFF

.word 0x0000

.word 0x9200

.word 0x0000

/* GDT table pointer */

gdtptr:

.word 0x27 /* Limit */

.long gdt /* Base Address */

/* Initial GDT table pointer for multiboot */

gdtptrhigh:

.word 0x27 /* Limit */

.long gdt + INITIAL_BASE - FREELDR_BASE /* Base Address */

/* real-mode IDT pointer */

rmode_idtptr:

.word 0x3ff /* Limit */

.long 0 /* Base Address */

mb_info:

.fill MB_INFO_SIZE,1,0

cmdline:

.fill CMDLINE_SIZE,0

EXTERN(_BootDrive)

.long 0

EXTERN(_BootPartition)

.long 0

,看完了,总结下

这个文件里函数的调用基本步骤:

1,数据初始化

2,加载GDT

3,加载LDT

4,修改CR0PE位进入保护模式

5,跳转到保护模式下

6,保存全局变量

7,调用_BootMain调用FreeLdr

8,修改CR0PE位进入实模式

9,加载实模式的LDT

10,重新启动.

虽然下面的EnableA20disableA20没用到吧,这里我也说下他们是干嘛的,其实代码作者也注释上了”to allow access to over 1mb”就是为访问大于1M的内存地址,参考《自己动手写操作系统》上的一段内容是:

什么是A20?这是一个历史问题,8086是采用SEG:OFFSET的模式分段的,所以他的最大内存是FFFF:FFFF10FFEFh,但是8086只有20根地址总线,只能寻址到1Mb,如果试图访问超过1MB的地址时会怎样呢?实际上系统并不会发生异常.而是回卷回去,重新从地址0开始寻址,可是到了80286系列时,真的可以访问到1MB以上的内存地址了,如果遇到同样的情况系统不会再回卷寻址,这就造成了向上不兼容,为了保证百分之百兼容,IBM想出一个办法使用键盘来控制第20个地址位,这就是A20地址线,如果不开A20地址线总会是0.为了访问所有内存,我们需要打开A20地址线,默认是关闭的,但是怎么打开A20地址线呢?我们可以通过92h端口来达到目的..

知识点:

1,AT&T汇编

2,实模式和保护模式和其相互转换(具体参见《自己动手写操作系统》一书)

3,A20地址的打开方法.

4,几种C语言函数的调用方式.

5,Int 19h是干什么用的?(代码里的红字介绍了)

.Net中的反应式编程(Reactive Programming)

.Net中的反应式编程(Reactive Programming)

系列主题:基于消息的软件架构模型演变

 

一、反应式编程(Reactive Programming)

1、什么是反应式编程:反应式编程(Reactive programming)简称Rx,他是一个使用LINQ风格编写基于观察者模式的异步编程模型。简单点说Rx = Observables + LINQ + Schedulers。

2、为什么会产生这种风格的编程模型?我在本系列文章开始的时候说过一个使用事件的例子:

          var watch = new FileSystemWatcher();
            watch.Created += (s,e) =>
            {
                var fileType = Path.GetExtension(e.FullPath);
                if (fileType.ToLower() == "jpg")
                {
                    //do some thing
                }
            };

这个代码定义了一个FileSystemWatcher,然后在Watcher事件上注册了一个匿名函数。事件的使用是一种命令式代码风格,有没有办法写出声明性更强的代码风格?我们知道使用高阶函数可以让代码更具声明性,整个LINQ扩展就是一个高阶函数库,常见的LINQ风格代码如下:

var list = Enumerable.Range(1,10)
                .Where(x => x > 8)
                .Select(x => x.ToString())
                .First();

能否使用这样的风格来编写事件呢?

3、事件流
LINQ是对IEnumerable<T>的一系列扩展方法,我们可以简单的将IEnumerable<T>认为是一个集合。当我们将事件放在一个时间范围内,事件也变成了集合。我们可以将这个事件集合理解为事件流。

事件流的出现给了我们一个能够对事件进行LINQ操作的灵感。

二、反应式编程中的两个重要类型

事件模型从本质上来说是观察者模式,所以IObservable<T>和IObserver<T>也是该模型的重头戏。让我们来看看这两个接口的定义:

    public interface IObservable<out T>
    {
          //Notifies the provider that an observer is to receive notifications.
          Idisposable Subscribe(IObserver<T> observer);
    }
    public interface IObserver<in T>
    {
        //Notifies the observer that the provider has finished sending push-based notifications.
        void OnCompleted();

        //Notifies the observer that the provider has experienced an error condition.
        void OnError(Exception error);
       
        //Provides the observer with new data.
        void OnNext(T value);
    }

这两个名称准确的反应出了它两的职责:IObservable<T>-可观察的事物,IObserver<T>-观察者。

IObservable<T>只有一个方法Subscribe(IObserver<T> observer),此方法用来对事件流注册一个观察者。

IObserver<T>有三个回调方法。当事件流中有新的事件产生的时候会回调OnNext(T value),观察者会得到事件中的数据。OnCompleted()和OnError(Exception error)则分别用来通知观察者事件流已结束,事件流发生错误。

显然事件流是可观察的事物,我们用Rx改写上面的例子:

Observable.FromEventPattern<FileSystemEventArgs>(watch,"Created")
                .Where(e => Path.GetExtension(e.EventArgs.FullPath).ToLower() == "jpg")
                .Subscribe(e =>
                {
                    //do some thing
                });

注:在.net下使用Rx编程需要安装以下Nuget组件:

Install-Package Rx-main

三、UI编程中使用Rx

Rx模型不但使得代码更加具有声明性,Rx还可以用在UI编程中。

1、UI编程中的第一段Rx代码

为了简单的展示如何在UI编程中使用Rx,我们以Winform中的Button为例,看看事件模型和Rx有何不同。

       private void BindFirstGroupButtons()
        {
            btnFirstEventMode.Click += btnFirstEventMode_Click;
        }

        void btnFirstEventMode_Click(object sender,EventArgs e)
        {
            MessageBox.Show("hello world");
        }

添加了一个Button,点击Button的时候弹出一个对话框。使用Rx做同样的实现:

            //得到了Button的Click事件流。
            var clickedStream = Observable.FromEventPattern<EventArgs>(btnFirstReactiveMode,"Click");
            //在事件流上注册了一个观察者。 
            clickedStream.Subscribe(e => MessageBox.Show("Hello world"));

有朋友指出字符串“Click”非常让人不爽,这确实是个问题。由于Click是一个event类型,无法用表达式树获取其名称,最终我想到使用扩展方法来实现:

        public static IObservable<EventPattern<EventArgs>> FromClickEventPattern(this Button button)
         {
             return Observable.FromEventPattern<EventArgs>(button,"Click");
         }

         public static IObservable<EventPattern<EventArgs>> FromDoubleClickEventPattern(this Button button)
         {
             return Observable.FromEventPattern<EventArgs>(button,"DoubleClick");
         }

我们平时常用的事件类型也就那么几个,可以暂时通过这种方案来实现,该方案算不上完美,但是比起直接使用字符串又能优雅不少。

btnFirstReactiveMode.FromClickEventPattern()
                .Subscribe(e => MessageBox.Show("hello world"));

2、UI编程中存在一个很常见的场景:当一个事件的注册者阻塞了线程时,整个界面都处于假死状态。.net中的异步模型也从APM,EAP,TPL不断演化直至async/await模型的出现才使得异步编程更加简单易用。我们来看看界面假死的代码:

       void btnSecondEventMode_Click(object sender,EventArgs e)
        {
            btnSecondEventMode.BackColor = Color.Coral;
            Thread.Sleep(2000);
            lblMessage.Text = "event mode";
        }

Thread.Sleep(2000);模拟了一个长时间的操作,当你点下Button时整个界面处于假死状态并且此时的程序无法响应其他的界面事件。传统的解决方案是使用多线程来解决假死:

          BtnSecondEventAsyncModel.BackColor = Color.Coral;

            Task.Run(() =>
            {
                Thread.Sleep(2000);
                Action showMessage = () => lblMessage.Text = "async event mode";
                lblMessage.Invoke(showMessage);
            });

这个代码的复杂点在于:普通的多线程无法对UI进行操作,在Winform中需要用Control.BeginInvoke(Action action)经过包装后,多线程中的UI操作才能正确执行,WPF则要使用dispatcher.BeginInvoke(Action action)包装。

Rx方案:

btnSecondReactiveMode.FromClickEventPattern()
                .Subscribe(e =>
                {
                    Observable.Start(() =>
                    {
                        btnSecondReactiveMode.BackColor = Color.Coral;
                        Thread.Sleep(2000);
                        return "reactive mode";
                    })
                        .SubscribeOn(ThreadPoolScheduler.Instance)
                        .ObserveOn(this)
                        .Subscribe(x =>
                        {
                            lblMessage.Text = x;
                        });
                });

一句SubscribeOn(ThreadPoolScheduler.Instance)将费时的操作跑在了新线程中,ObserveOn(this)让后面的观察者跑在了UI线程中。

注:使用ObserveOn(this)需要使用Rx-WinForms

Install-Package Rx-WinForms

这个例子虽然成功了,但是并没有比BeginInvoke(Action action)的方案有明显的进步之处。在一个事件流中再次使用Ovservable.Start()开启新的观察者让人更加摸不着头脑。这并不是Rx的问题,而是事件模型在UI编程中存在局限性:不方便使用异步,不具备可测试性等。以XMAL和MVVM为核心的UI编程模型将在未来处于主导地位,由于在MVVM中可以将UI绑定到一个Command,从而解耦了事件模型。

开源项目ReactiveUI提供了一个以Rx基础的UI编程方案,可以使用在XMAL和MVVM为核心的UI编程中,例如:Xamarin,WFP,Windows Phone8等开发中。

注:在WPF中使用ObserveOn()需要安装Rx-WPF

Install-Package Rx-WPF

3、再来一个例子,让我们感受一下Rx的魅力

界面上有两个Button分别为+和-操作,点击+按钮则+1,点击-按钮则-1,最终的结果显示在一个Label中。
这样的一个需求使用经典事件模型只需要维护一个内部变量,两个按钮的Click事件分别对变量做加1或减1的操作即可。
Rx作为一种函数式编程模型讲求immutable-不可变性,即不使用变量来维护内部状态。

            var increasedEventStream = btnIncreasement.FromClickEventPattern()
                .Select(_ => 1);
            var decreasedEventStream = btnDecrement.FromClickEventPattern()
                .Select(_ => -1);

            increasedEventStream.Merge(decreasedEventStream)
                .Scan(0,(result,s) => result + s)
                .Subscribe(x => lblResult.Text = x.ToString());

这个例子使用了IObservable<T>的”谓词”来对事件流做了一些操作。

  • Select跟Linq操作有点类似,分别将两个按钮的事件变形为IObservable<int>(1)和IObservable<int>(-1);
  • Merge操作将两个事件流合并为一个;
  • Scan稍显复杂,对事件流做了一个折叠操作,给定了一个初始值,并通过一个函数来对结果和下一个值进行累加;

下面就让我们来看看IObservable<T>中常用的“谓词”

四、IObservable<T>中的谓词

IObservable<T>的灵感来源于LINQ,所以很多操作也跟LINQ中的操作差不多,例如Where、First、Last、Single、Max、Any。
还有一些“谓词”则是新出现的,例如上面提到的”Merge”、“Scan”等,为了理解这些“谓词”的含义,我们请出一个神器RxSandbox。

1、Merge操作,从下面的图中我们可以清晰的看出Merge操作将三个事件流中的事件合并在了同一个时间轴上。

2、Where操作则是根据指定的条件筛选出事件。

有了这个工具我们可以更加方便的了解这些“谓词”的用途。

五、IObservable<T>的创建

Observable类提供了很多静态方法用来创建IObservable<T>,之前的例子我们都使用FromEventPattern方法来将事件转化为IObservable<T>,接下来再看看别的方法。

Return可以创建一个具体的IObservable<T>:

       public static void UsingReturn()
        {
            var greeting = Observable.Return("Hello world");
            greeting.Subscribe(Console.WriteLine);
        }

Create也可以创建一个IObservable<T>,并且拥有更加丰富的重载:

       public static void UsingCreate()
        {
            var greeting = Observable.Create<string>(observer =>
            {
                observer.OnNext("Hello world");
                return disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
            });

            greeting.Subscribe(Console.WriteLine);
        }

Range方法可以产生一个指定范围内的IObservable<T>

 Observable.Range(1,10)
           .Subscribe(x => Console.WriteLine(x.ToString()));

Generate方法是一个折叠操作的逆向操作,又称Unfold方法:

       public static void UsingGenerate()
        {
            var range = Observable.Generate(0,x => x < 10,x => x + 1,x => x);
            range.Subscribe(Console.WriteLine);
        }

Interval方法可以每隔一定时间产生一个IObservable<T>:

Observable.Interval(TimeSpan.FromSeconds(1))
           .Subscribe(x => Console.WriteLine(x.ToString()));

Subscribe方法有一个重载,可以分别对Observable发生异常和Observable完成定义一个回调函数。

 Observable.Range(1,10)
           .Subscribe(x => Console.WriteLine(x.ToString()),e => Console.WriteLine("Error" + e.Message),() => Console.WriteLine("Completed"));

还可以将IEnumerable<T>转化为IObservable<T>类型:

Enumerable.Range(1,10).ToObservable()
          .Subscribe(x => Console.WriteLine(x.ToString()));

也可以将IObservable<T>转化为IEnumerable<T>

var list= Observable.Range(1,10).ToEnumerable();

六、Scheduler

Rx的核心是观察者模式和异步,Scheduler正是为异步而生。我们在之前的例子中已经接触过一些具体的Scheduler了,那么他们都具体是做什么的呢?

1、先看下面的代码:

        public static void UsingScheduler()
        {
            Console.WriteLine("Starting on threadId:{0}",Thread.CurrentThread.ManagedThreadId);
            var source = Observable.Create<int>(
            o =>
            {
                Console.WriteLine("Invoked on threadId:{0}",Thread.CurrentThread.ManagedThreadId);
                o.OnNext(1);
                o.OnNext(2);
                o.OnNext(3);
                o.OnCompleted();
                Console.WriteLine("Finished on threadId:{0}",Thread.CurrentThread.ManagedThreadId);
                return disposable.Empty;
            });
            source
            //.SubscribeOn(NewThreadScheduler.Default)
            //.SubscribeOn(ThreadPoolScheduler.Instance)
            .Subscribe(
            o => Console.WriteLine("Received {1} on threadId:{0}",Thread.CurrentThread.ManagedThreadId,o),() => Console.WriteLine("OnCompleted on threadId:{0}",Thread.CurrentThread.ManagedThreadId));
            Console.WriteLine("Subscribed on threadId:{0}",Thread.CurrentThread.ManagedThreadId);
        } 

当我们不使用任何Scheduler的时候,整个Rx的观察者和主题都跑在主线程中,也就是说并没有异步执行。正如下面的截图,所有的操作都跑在threadId=1的线程中。

当我们使用SubscribeOn(NewThreadScheduler.Default)或者SubscribeOn(ThreadPoolScheduler.Instance)的时候,观察者和主题都跑在了theadId=3的线程中。

这两个Scheduler的区别在于:NewThreadScheduler用于执行一个长时间的操作,ThreadPoolScheduler用来执行短时间的操作。

2、SubscribeOn和ObserveOn的区别

上面的例子仅仅展示了SubscribeOn()方法,Rx中还有一个ObserveOn()方法。stackoverflow上有一个这样的问题:What's the difference between SubscribeOn and ObserveOn,其中一个简单的例子很好的诠释了这个区别。

        public static void DifferenceBetweenSubscribeOnAndobserveOn()
        {
            Thread.CurrentThread.Name = "Main";

            IScheduler thread1 = new NewThreadScheduler(x => new Thread(x) { Name = "Thread1" });
            IScheduler thread2 = new NewThreadScheduler(x => new Thread(x) { Name = "Thread2" });

            Observable.Create<int>(o =>
            {
                Console.WriteLine("Subscribing on " + Thread.CurrentThread.Name);
                o.OnNext(1);
                return disposable.Create(() => { });
            })
            //.SubscribeOn(thread1)
            //.ObserveOn(thread2)
            .Subscribe(x => Console.WriteLine("Observing '" + x + "' on " + Thread.CurrentThread.Name));
        }
  • 当我们注释掉:SubscribeOn(thread1)和ObserveOn(thread2)时的结果如下:

    观察者和主题都跑在name为Main的thread中。

  • 当我们放开SubscribeOn(thread1):

    主题和观察者都跑在了name为Thread1的线程中

  • 当我们注释掉:SubscribeOn(thread1),放开ObserveOn(thread2)时的结果如下:

    主题跑在name为Main的主线程中,观察者跑在了name=Thread2的线程中。

  • 当我们同时放开SubscribeOn(thread1)和ObserveOn(thread2)时的结果如下:

    主题跑在name为Thread1的线程中,观察者跑在了name为Thread2的线程中。

至此结论应该非常清晰了:SubscribeOn()和ObserveOn()分别控制着主题和观察者的异步。

七、其他Rx资源

除了.net中的Rx.net,其他语言也纷纷推出了自己的Rx框架。

  • RxJS: Javascript中的Rx
  • RxCpp:C++中的Rx
  • Rx.rb: Ruby中的Rx
  • RxPy:python中的Rx

 

参考资源:

http://rxwiki.wikidot.com/101samples

http://introtorx.com/Content/v1.0.10621.0/01_WhyRx.html#WhyRx

http://www.codeproject.com/Articles/646361/Reactive-Programming-For-NET-And-Csharp-Developers

8 Traits of an Experienced Programmer that every beginner programmer should know

8 Traits of an Experienced Programmer that every beginner programmer should know

Referrence: http://whats-online.info/guides-and-info/36/Traits-of-Experienced-Programmer-that-every-beginner-should-know/

Not everybody has the capability to be a good programmer. Most lack the desire,others do not have a high level of practical aptitude and others lack the personality required to make a good programmer. To help you understand just what these ‘personality’ traits are,I will break down some of the traits that an experienced programmer has. Being in the field for 8 years Now,believe me I kNow the ups,downs,tricks and ‘’oh no’s’’ in this field. I will take you through 8 crucial traits of a programmer,which can be emulated by the beginners who wanna make it big in this field.

  1. Consistency

No programmer wants to be the wonder hit-and-disappear kind of a programmer. A good programmer is reliable. He kNows what it is that he wants,and is willing to keep on programming when need be. Not necessarily a 9-5 person,but one who accomplishes tasks and projects without leaving them hanging.

  1. Problem solver

As a programmer,I would liken programming to solving a complicated mathematics equations. They are complicated and most seem hard to crack. It is easy to just let go of them and look for a simpler equation to tackle. A programmer is that person who doesn’t give up on a task simply because it seems complicated. They look for solutions to every task. Giving up is a phrase that is never heard of in the world of programming.

  1. Planning skills

To plan is to see ahead. Instead of hopping into a new project,a good programmer will first study as much as he/ she can concerning the anticipated end product. As soon as that analysis is completed,the programmer ought to first strategize the project structure before inputting the first line of code. Planning goes hand in hand with consistency. So a consistent programmer is also a good planner.

  1. Excellent communication skills

I do not speak the perfect English,but am I good programmer? The answer is yes. Across the years,I have noticed that most of my peers are not fluent English speaker but they do pass for programmers with excellent communication skills. In programming,good communication skills is the ability to express an idea precisely and efficiently. Good programmers are able to pass their points across well. Programmers who experience a tough time conveying their points across or comprehending what others are telling them,may not be successful in the long run.

  1. Passion for Programming

This is the most important trait of all times. Passion is everything. Without the willingness to work,it will soon or later go down the drain. Some employed programmers only do the 9 to 5 job,for the salary part of it. These caliber of programmers do not program for long because they only do it for the cash,not for the work. When off from work,nothing close to what they do ever crosses their minds. You do not have to wake up,and go to bed breathing codes. Programmers who lack the passion are never enthused to acquire the best method of doing things and instead,they only engage in a routine,which is not be the best technique of doing things.

  1. Detail Oriented

This is what separates a patient programmer from an impatient one. Programming involves dealing with codes whose simple mistake Could cost you a whole project. A programmer who pays close consideration to detail will be suggestively more industrIoUs than the one who doesn‘t. This trait involves evaluation of self –conscIoUsness,which is very crucial for a serIoUs consistent programmer.

  1. Ability to cope with changing trends

Technology is constantly changing and the expertise and capabilities a programmer has currently will probably be out-of-date in the coming years. It is,therefore,key for a programmer to be able and willing to educate him/ herself and follow the up-to-date trends. This way,they find it easy to take part in any ongoing education chances that are presented.

  1. A good reader

A good programmer reads extensively. Not all the work is about coding. A substantial percentage of a programmer‘s work day is spent in reading. It Could be codes typed by other people,Web sites with examples,papers,or projects. Programmers who do not read extensively,or worse,do not comprehend what they are reading,are mostly incompetent at best,and hazardous at worst.

All in all,a good programmer

? Recognizes that programming is a resourceful art and is nothing interesting

? Takes boundless pride in his job and gets abundant contentment from it

? Attempts to decrease the difficulty of both the problem at hand and the result

? He/she utilizes his time but is never too occupied to help others hit the books

? He/she appreciates positive criticism and offers productive criticism for other programmers as well.

? Has Failed countless times but is always willing to learn from the failures.

? Makes his/her decisions without necessarily relying on other people. Sometimes someone needs to make decisions from his/ her heart without the influence of others.

? is continually learning and gets an excitement from those embarrassing moments. nothing is too serIoUs. Laugh at yourself at times.

Programming is not for the faint-hearted. Do not try programming at your desperation when everything else Could not work out. If you possess the above traits that a good programmer should have,then brace yourself for a life changing experience. Above all,hard work is everything.

Cg Programming/ProgrammableGraphics Pipeline

Cg Programming/ProgrammableGraphics Pipeline

前言:本文是Cg Wiki系列的一篇 该系从两个方面来---Shader背后的图形原理,一些常见的Shader事例,为unity中的Shader做出讲解,我会坚持翻译下去,和大家一起学习.
由于本人刚刚开始翻译所以如果有翻译错的地方,还请大家轻拍
========================================================
Cg Programming/ProgrammableGraphics Pipeline
-------------------------------------------------------------
Cg 编程语言/可编程图形管线
Contents
本节内容
· 1Parallelismin Graphics Pipelines
· 1图形管线中的并行计算
· 2Programmableand Fixed-Function Stages
· 2可编程阶段和固定功能阶段
· 3Data Flow
· 3数据流
· 4FurtherReading
· 4拓展阅读
Theprogrammable graphics pipeline presented here is very similar to the OpenGL(ES) 2.0 pipeline,the WebGL pipeline,and the Direct3D 8.0 pipeline. As suchit is the lowest common denominator of programmable graphics pipelines of themajority of today's desktop PCs and mobile devices.
本节所讲到的的可编程的图形管线和OpenGL(ES)2.0管线,WebGL管线以及Direct3D 8.0管线都十分类似。它是当今主流桌面PC以及移动设备可编程图形管线中的最基本的标准。

Parallelism in Graphics Pipelines
图形管线中的并行计算
GPUsare highly parallel processors. This is the main reason for their performance.In fact,they implement two kinds of parallelism: vertical and horizontalparallelism:
出于性能方面的考虑,GPU(图形处理单元)一般都具有能进行高效并行计算的处理器。实际上,GPU能进行两种并行计算:垂直并行计算和水平并行计算

Ford assembly line,1913.(1913年,福特汽车的流水线)
· Vertical parallelism describes parallel processingat different stages of a pipeline. This concept was also crucial inthe development of the assembly line at Ford Motor Company: many workers canwork in parallel on rather simple tasks. This made mass production (andtherefore mass consumption) possible. In the context of processing units in GPUs,the simple tasks correspond to less complex processing units,which save costsand power consumption.
· 垂直并行计算指的是能同时处理处于 管线中的不同阶段的计算。这种理念对于福特汽车公司的装配件流水线作业来说也起着非常重要的作用:很多工人都只需要在流水线上做一些很简单的工作即可。这使得庞大的生产过程(以及消耗过程)变得可能。对于GPU中的处理单元而言,简单工作就是减少具有计算复杂运算能力的处理单元,这样不仅能减少花费也能节能。
·
Assembly plant of the Bell Aircraft Corporation withmultiple parallel assembly lines,ca. 1944.1994年,贝尔航空公司具有多条并行作业流水线的工厂
· Horizontal parallelism describes the possibility toprocess work in multiple pipelines. This allows for even moreparallelism than the vertical parallelism in a single pipeline. Again,theconcept was also employed at Ford Motor Company and in many other industries.In the context of GPUs,horizontal parallelism of the graphics pipeline was animportant feature to achieve the performance of modern GPUs.
· 水平并行计算指的是在 多条渲染管线上同时处理任务的可行性。这使得并行计算并不仅仅局限于在单一的一条管线上的不同阶段进行垂直并行计算。同样的,这个理念在福特汽车公司和许多工厂制造情境中也都得到了广泛的应用。对于GPU而言,拥有具有水平并行计算的图形渲染管线是当代GPU能达到合格性能的重要特征之一。

Thefollowing diagram shows an illustration of vertical parallelism (processing instages represented by Boxes) and horizontal parallelism (multiple processingunits for each stage represented by multiple arrows between Boxes).
这个图表展示出了垂直并行计算(用底色标签表示出了不同阶段的处理过程)和水平并行计算(用在两个底色标签间的大量箭头表示出了每个阶段间的大量处理单元)

Vertex Data(顶点数据)
e.g. trianglemeshes provided by 3D modeling tools. 3D 建模 件提供的数据,例如三角形网格
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
many verticesare processed in parallel
处于并行处理 程中的许多
Vertex Shader(顶点着色器)
a small programin Cg (or another shading language) is applied to each vertex
用在每个 点上的用Cg或者其他着色器 编写 的一小段程序
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
PrimitiveAssembly(图元装配)
setup ofprimitives,e.g. triangles,lines,and points
例如三角形,直 线 ,点 不同图元进行装配
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
many primitivesare processed in parallel
并行 算的 元装配
Rasterization(光栅化)
interpolation ofdata for all pixels covered by the primitive (e.g. triangle)
根据各种 元(比如三角形) 所有像素点 据的
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
many fragments(corresponding to pixels) are processed in parallel
并行 算的 多片段( 对应 着像素)处理过程
Fragment Shader(片段着色器)
a small programin Cg (or another shading language) is applied to each fragment (i.e. coveredpixel)
每个片段(也就是像素) 行的一小段用 Cg 或者其他着色器 编写 的程序
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Per-FragmentOperations(逐片段处理)
configurableoperations on each fragment (i.e. covered pixel)
每个片段(也就是像素) 行配置运算
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
results of manyfragments are written in parallel to the framebuffer
片段的计算 果被并行地 入到 帧缓 存中
Framebuffer(帧缓存)
array of pixelsin which the computed fragment colors are stored
保存通 过计 算得出后的片段 色的 数组

In the following diagrams,there is only one arrow between any two stages.However,it should be understood that GPUs usually implement the graphicspipeline with massive horizontal parallelism. Only software implementations ofthe graphics pipeline,e.g. Mesa 3D (see the Wikipedia entry),usually implement a single pipeline.
在上面的图示中,虽然这里只在两个阶段间表示出了一种箭头,但是应该能明白GPU通常在图形管线中使用了大量的水平并行计算。只有一些软件(比如Mesa3D)能够只在单一一条管线上进行渲染。

Programmable and Fixed-FunctionStage
可编程阶段和固定功能阶段

Thepipelines of OpenGL ES 1.x,core OpenGL 1.x,and Direct3D 7.x are configurablefixed-function pipelines,i.e. there is no possibility to include programs inthese pipelines. In OpenGL (ES) 2.0,WebGL,and Direct3D 8.0,two stages (thevertex shader and the fragment shader stage) of the pipeline are programmable,i.e. small programs (shaders) written in Cg (or another shading language) areapplied in these stages. In the following diagram,programmable stages arerepresented by green Boxes,fixed-function stages are represented by grayBoxes,and data is represented by blue Boxes.
OpenGLES 1系列,核心OpenGL1系列以及Direct3D 7系列的管线都是只包含一些可以设置参数的固定功能管线,也就是说,这些管线没有编程能力。在OpenGL(ES) 2.0,WebGL以及Direct3D8.0开始,处于两个阶段(顶点着色器以及片段着色器)的渲染过程都拥有了可编程能力,也就是说,一些用Cg或者其他着色器语言编写的小程序能够应用到这两个阶段中。在下面的图示中,可编程的阶段将用绿色底色标签表示出来,固定功能阶段用将用蓝色底色标签标出来。

Vertex Data(顶点数据)
e.g. trianglemeshes provided by 3D modeling tools
3D建模工具提供的数据,比如三角形
Vertex Shader(顶点着色器)
a small programin Cg is applied to each vertex
作用在每个点上的一小段Cg程序
PrimitiveAssembly(图元装配)
setup ofprimitives,and points
对图元例如三角形,线段,点行装配
Rasterization(光栅化)
interpolation ofdata (e.g. color) for all pixels covered by the primitive
对图元覆盖的每个像素据(比如色)
Fragment Shader(片段着色器)
a small programin Cg is applied to each fragment (i.e. covered pixel)
作用在每个片段(也就是像素)上的一小段Cg程序
Per-FragmentOperations(逐片段处理)
configurableoperations on each fragment (i.e. covered pixel)
每个像素配置运算
Framebuffer(帧缓存)
array of pixelsin which the computed fragment colors are stored
由片段中算出成的像素数组

The vertex shader and fragment shader stages are discussed in more detail inthe platform-specific tutorials. The rasterization stage is discussed in Section“Rasterization” and theper-fragment operations in Section “Per-FragmentOperations”.
在特定平台的教程中有对顶点着色器和片段着色器这两个阶段的更详细的阐述。光栅化将在『光栅化』章节中进行阐述,逐片段处理操作将在『逐片段处理操作』章节中进行阐述。

Theprimitive assembly stage mainly consists of clipping primitives to the viewfrustum (the part of space that is visible on the screen) and optional cullingof front-facing and/or back-facing primitives. These possibilities arediscussed in more detail in the platform-specific tutorials.
图元装配阶段主要包括了:根据视锥体(屏幕中的一部分可见区域)进行剪裁,以及根据选择,对朝向正面或者背面的图元进行剪裁。有关的具体过程将在特定平台的教程中进行阐述。

Data Flow
数据流

Inorder to program Cg vertex and fragment shaders,it is important to understandthe input and ouput of each shader. To this end,it is also useful tounderstand how data is communicated between all stages of the pipeline. This isillustrated in the next diagram:
为了对顶点和片段着色器进行编程,理解每个着色器的输入和输出是很重要的。在这之后,理解数据是如何在渲染管线的不同阶段间联系起来的也很有帮助。用下面的图表来进行说明:

Vertex Data(顶点数据)
vertex inputparameters with semantics (e.g. POSITION , COLOR , norMAL , TEXCOORD0 , TEXCOORD1 ,etc.)
义(如 POSITION COLOR norMAL TEXCOORD0 TEXCOORD1 等等) 定的 点输入参
Vertex Shader(顶点着色器)
uniformparameters; in some cases texture data (images)
uniform参数,在一些情况下还有图片数据
vertex outputparameters with semantics (in particular POSITION , SV_POSITION ,and PSIZE but also COLOR ,etc.)
义(如 POSITION SV_POSITION 以及PSIZE 同样也有 TEXCOORD0 TEXCOORD1 等等) 定的 点输出参
PrimitiveAssembly(图元装配)
vertex outputparameters
点输出参
Rasterization(光栅化)
fragment inputparameters (interpolated at pixels) with semantics (corresponding tosemantics of the vertex output parameters)
定了(和 点输出参 对应 的) 义的片段(是经 过内 算后的像素)输入参
Fragment Shader(片段着色器)
uniformparameters (constant for each primitive) and texture data
uniform参数(对于每个图元来说都是一个常量)以及图片数据
fragment outputparameters with semantics (in particular COLOR and DEPTH )
定了 义(特 是COLOR和DEPTH)的片段输出参
Per-FragmentOperations(逐片段处理操作)
fragment colorand fragment depth 片段的 色和深度
Framebuffer(帧缓存)


Vertex input parameters are defined based on the vertex data. Foreach vertex input parameter a semantic has to be defined,which specifies how the parameter relates to data in the fixed-functionpipeline. Examples of semantics are POSITION,COLOR,norMAL,TEXCOORD0,TEXCOORD1,etc. This makes it possible to use Cg programs even with APIs that wereoriginally designed for a fixed-function pipeline. For example,the vertexinput parameter for vertex positions should use the POSITION semanticsuch that all APIs can provide the appropriate data for this input parameter.Note that the vertex position is in object coordinates,i.e. this is theposition as specified in a 3D modeling tool.
顶点的输入参数是根据顶点数据而来的。对于每一个顶点输入参数而言,因为语义要用来约定在固定功能管线阶段参数是如何关联到数据的,所以参数都要定义语义。比如POSITION,COLOR,norMAL,TEXCOORD0,TEXCOORD1等等这些语义。这样之后才能正确使用Cg程序甚至其他一些基于固定功能管线设置出来的API接口。比如,对于每个表示顶点的位置的顶点输入参数都要绑定POSITION语义,这样之后API才能给输入参数提供恰当的数据。注意顶点位置是相对物体坐标系而言的,也就是说,这个位置是在3D建模工具中定下来的。

Uniformparameters (or uniforms) have the same value for all vertexshaders and all fragment shaders that are executed when rendering a specificprimitive (e.g. a triangle). However,they can be changed for other primitives.Usually,they have the same value for a large set of primitives that make up amesh. Typically,vertex transformations,specifications of light sources andmaterials,etc. are specified as uniforms.
Uniform参数(或者说uniforms)在渲染同一个特定图元(比如三角形)时,对于所有起作用的顶点着色器和片段着色器都具有相同的值。然而,对于其他图元来说,他们可能会改变值。通常情况下,对于构成网格的大多数图元来说,他们的值都是相同的。典型的是关于顶点变换,光源描述以及材质等等情况中数据参数都被定义成了uniforms。

Vertexoutput parameters are computed by the vertexshader,i.e. there is one set of values of these parameters for each vertex. Asemantic has to be specified for each parameter,e.g. POSITION,SV_POSITION,etc. Usually,there has to be an output parameter with the semantic POSITION or SV_POSITION,which determines where a primitive is rendered on the screen (“SV” stands for“system value” and can have a special meaning). The size of point primitivescan be specified by an output parameter with the semantic PSIZE.Other parameters are interpolated (see Section“Rasterization”) for each pixelcovered by a primitive.
顶点输出参数是经过了顶点着色器计算之后的值,也就是说,每个顶点都有一组相关量的参数。每个参数必须和一个语义(比如,POSITION,SV_POSITION,COLOR,TEXCOORD0,TEXCOORD1等等)绑定。通常情况下,必须要有一个参数和用来决定图元渲染在屏幕的哪个位置,并且与POSITION语义或者SV_POSITION(『SV』是『system value』系统值的缩写有着特殊的意义)语义绑定在一起。点图元的大小可以根据绑定了PSIZE的输出参数来获取。在一个图元中的每个像素会内插计算其他的参数(参考『光栅化』章节)。

Fragmentinput parameters are interpolated from thevertex output parameters for each pixel covered by a primitive. Similar tovertex output parameters,a semantic has to be specified for each fragmentinput parameter. These semantics are used to match vertex output parameterswith fragment input parameters. Therefore,the names of correspondingparameters in the vertex shader and fragment shader can be different as long asthe semantics are the same.
片段输入参数是根据顶点输出参数内插计算之后,在被图元覆盖的每个像素得到的数据。和顶点输出参数类似,每个片段输入参数都要和一个语义绑定。这些语义使得片段输入参数和顶点输出参数相匹配上。所以只要顶点输出参数和片段输入参数语义相同,他们的参数名可以不同。

Fragmentoutput parameters are computed by fragmentshaders. A semantic has to be specified,which determines how the value is usedin the following fixed-function pipeline. Most fragment shaders specify anoutput parameter with the semantic COLOR.The fragment depth is computed implicitly even if no output parameter with thesemantic DEPTH is specified.
片段输出参数是经过片段着色器计算之后的值。因为要来说明这个值在接下来的固定功能管线阶段的用途,所以必须要绑定一个语义。大多数片段着色器都将输出参数和COLOR语义绑定在一起。即使没有绑定DEPTH语义的输出参数,片段的深度值也会被隐式计算出来。

Texturedata include a uniform sampler,which specifies thetexture sampling unit,which in turn specifies the texture image from whichcolors are fetched.
图片数据包括了一张用来定义如何根据图片采样单位来从图片文件中取得颜色的采样图。

Otherdata is described in the tutorials for specific platforms.
其他数据会在具体平台的教程中做阐述。

Further Reading
拓展阅读
Themodel of the programmable graphics pipeline used by Cg is described inthe first chapter of Nvidia's Cg Tutorial.
在Nvidia的Cg教程中的第一章阐述的有关Cg中的可编程图形管线模型。

com.facebook.react.views.progressbar.ReactProgressBarViewManager的实例源码

com.facebook.react.views.progressbar.ReactProgressBarViewManager的实例源码

项目:react-native-gcm-android    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Arrays.<ViewManager>asList(
            new ReactDrawerLayoutManager(),new ReacthorizontalscrollviewManager(),new ReactimageManager(),new ReactProgressBarViewManager(),new ReactRawTextManager(),new ReactScrollViewManager(),new ReactSwitchManager(),new ReactTextInputManager(),new ReactTextViewManager(),new ReactToolbarManager(),new ReactViewManager(),new ReactViewPagerManager(),new ReactTextInlineImageViewManager(),new ReactVirtualTextViewManager(),new SwipeRefreshLayoutManager(),new ReactWebViewManager());
}
项目:RNLearn_Project1    文件:ProgressBarTestCase.java   
@Override
protected void setUp() throws Exception {
  super.setUp();

  List<ViewManager> viewManagers = Arrays.<ViewManager>asList(
      new ReactViewManager(),new ReactProgressBarViewManager());
  mUIManager = new UIManagerModule(
      getContext(),viewManagers,new UIImplementationProvider(),false);
  UiThreadUtil.runOnUiThread(
      new Runnable() {
        @Override
        public void run() {
          mUIManager.onHostResume();
        }
      });
  waitForIdleSync();

  mInstance = ReactTestHelper.catalystInstanceBuilder(this)
      .addNativeModule(mUIManager)
      .addNativeModule(new AndroidInfoModule())
      .addNativeModule(new DeviceInfoModule(getContext()))
      .addNativeModule(new AppStateModule(getContext()))
      .addNativeModule(new FakeWebSocketModule())
      .addJSModule(ProgressBarTestModule.class)
      .build();

  mRootView = new ReactRootView(getContext());
  displayMetrics metrics = getContext().getResources().getdisplayMetrics();
  mRootView.setLayoutParams(
      new FrameLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels));
  int roottag = mUIManager.addMeasuredRootView(mRootView);
  mInstance.getJSModule(ProgressBarTestModule.class).renderProgressBarapplication(roottag);
  waitForBridgeAndUIIdle();
}
项目:ReactNativeSignatureExample    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    ARTRenderableViewManager.createARTGroupViewManager(),ARTRenderableViewManager.createARTShapeViewManager(),ARTRenderableViewManager.createARTTextViewManager(),new ARTSurfaceViewManager(),new ReactDialogPickerManager(),new ReactDrawerLayoutManager(),new ReactDropdownPickerManager(),new FrescoBasedReactTextInlineImageViewManager(),new ReactWebViewManager(),new RecyclerViewBackedScrollViewManager(),new SwipeRefreshLayoutManager());
}
项目:react-native-ibeacon-android    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    ARTRenderableViewManager.createARTGroupViewManager(),new SwipeRefreshLayoutManager());
}
项目:react-native-Box-loaders    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    ARTRenderableViewManager.createARTGroupViewManager(),new ReactModalHostManager(),new ReactSliderManager(),new SwipeRefreshLayoutManager());
}
项目:Ironman    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    ARTRenderableViewManager.createARTGroupViewManager(),new SwipeRefreshLayoutManager());
}
项目:Ironman    文件:ProgressBarTestCase.java   
@Override
protected void setUp() throws Exception {
  super.setUp();

  List<ViewManager> viewManagers = Arrays.<ViewManager>asList(
      new ReactViewManager(),new UIImplementationProvider());
  UiThreadUtil.runOnUiThread(
      new Runnable() {
        @Override
        public void run() {
          mUIManager.onHostResume();
        }
      });
  waitForIdleSync();

  mInstance = ReactTestHelper.catalystInstanceBuilder(this)
      .addNativeModule(mUIManager)
      .addNativeModule(new AndroidInfoModule())
      .addNativeModule(new FakeWebSocketModule())
      .addJSModule(ProgressBarTestModule.class)
      .build();

  mRootView = new ReactRootView(getContext());
  displayMetrics metrics = getContext().getResources().getdisplayMetrics();
  mRootView.setLayoutParams(
      new FrameLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels));
  int roottag = mUIManager.addMeasuredRootView(mRootView);
  mInstance.getJSModule(ProgressBarTestModule.class).renderProgressBarapplication(roottag);
  waitForBridgeAndUIIdle();
}
项目:RNLearn_Project1    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  List<ViewManager> viewManagers = new ArrayList<>();

  viewManagers.add(ARTRenderableViewManager.createARTGroupViewManager());
  viewManagers.add(ARTRenderableViewManager.createARTShapeViewManager());
  viewManagers.add(ARTRenderableViewManager.createARTTextViewManager());
  viewManagers.add(new ARTSurfaceViewManager());
  viewManagers.add(new ReactDialogPickerManager());
  viewManagers.add(new ReactDrawerLayoutManager());
  viewManagers.add(new ReactDropdownPickerManager());
  viewManagers.add(new ReacthorizontalscrollviewManager());
  viewManagers.add(new ReactimageManager());
  viewManagers.add(new ReactModalHostManager());
  viewManagers.add(new ReactProgressBarViewManager());
  viewManagers.add(new ReactRawTextManager());
  viewManagers.add(new ReactScrollViewManager());
  viewManagers.add(new ReactSliderManager());
  viewManagers.add(new ReactSwitchManager());
  viewManagers.add(new FrescoBasedReactTextInlineImageViewManager());
  viewManagers.add(new ReactTextInputManager());
  viewManagers.add(new ReactTextViewManager());
  viewManagers.add(new ReactToolbarManager());
  viewManagers.add(new ReactViewManager());
  viewManagers.add(new ReactViewPagerManager());
  viewManagers.add(new ReactVirtualTextViewManager());
  viewManagers.add(new ReactWebViewManager());
  viewManagers.add(new SwipeRefreshLayoutManager());

  SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(reactContext);
  if (preferences.getBoolean("flat_uiimplementation",false)) {
    viewManagers.addAll(Arrays.asList(
      new RCTViewManager(),new RCTTextManager(),new RCTRawTextManager(),new RCTVirtualTextManager(),new RCTTextInlineImageManager(),new RCtimageViewManager(),new RCTTextInputManager(),new RCTViewPagerManager(),new FlatARTSurfaceViewManager(),new RCTModalHostManager()));
  }

  return viewManagers;
}

今天的关于ReactOS 源码分析 (二) By:ProgrammeBoyreact源码深度解析 慕课网的分享已经结束,谢谢您的关注,如果想了解更多关于.Net中的反应式编程(Reactive Programming)、8 Traits of an Experienced Programmer that every beginner programmer should know、Cg Programming/ProgrammableGraphics Pipeline、com.facebook.react.views.progressbar.ReactProgressBarViewManager的实例源码的相关知识,请在本站进行查询。

本文标签: