GVKun编程网logo

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

16

在这里,我们将给大家分享关于ReactOS源码分析(一)by:ProgrammeBoy的知识,让您更了解react源码深度解析慕课网的本质,同时也会涉及到如何更有效地.Net中的反应式编程(React

在这里,我们将给大家分享关于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源码深度解析 慕课网)

ReactOS 源码分析

前言

ReactOS是一个开源的免费的操作系统,它致力于兼容现在最流行的操作系统windows,打破微软垄断的局面,这里我们为那些默默无闻的开发者致敬,他们开发reactos没有工资,没有补贴,没有只有默默的写代码这是一种精神..

代码分析

那我们就在最初引导阶段开始分析.首先我们假设我们的机器是i386机型. 引导磁盘是fat32格式.我的Reactos代码在D:/ReactOS/ReactOS_src/,代码版本0.39

1. 系统开始启动

首先机器加电自检,然后检查启动盘,是从光盘还是硬盘启动呢?可能大家都知道,这是在BIOS里面设置的,这里我们是研究已经安装好的系统启动过程,就磁盘启动啦,首先找到启动磁盘,BIOS会检查磁盘的00磁道,1扇区,如果发现其为55aa结尾而且小于512字节就认为他就是一个合法的引导扇扇区(BootSector),然后把这个引导代码加载到0000:7c000,然后跳转到这个地方执行,现在就把所有的控制权交给引导代码了,BIOS里的启动代码是固定在ROM里的,所以系统启动的代码就是那段引导程序代码,前面我们也假设了我们是fat32格式的磁盘.所以我们就从fat32.asm开始吧.

2 f at32.asm

代码位置: D:/ReactOS/ReactOS_src/boot/freeldr/bootsect/fat32.asm

代码如下:

;看了吧,这里就是把他加载到了0000:7c000

org 7c00h

segment .text

bits 16 ;16位程序

start:

jmp short main

nop

/*这里是什么?winhex打开磁盘,选在结构fat32的样式打开就可以看待这些数据了,

数据结构如下

typedef struct _FAT_BOOTSECTOR

{

UCHAR JumpBoot[3]; // Jump instruction to boot code

CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes

USHORT BytesPerSector; // Bytes per sector

UCHAR SectorsPerCluster; // Number of sectors in a cluster

USHORT ReservedSectors; // Reserved sectors,usually 1 (the bootsector)

UCHAR NumberOfFats; // Number of FAT tables

USHORT RootDirEntries; // Number of root directory entries (fat12/16)

USHORT TotalSectors; // Number of total sectors on the drive,16-bit

UCHAR MediaDescriptor; // Media descriptor byte

USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)

USHORT SectorsPerTrack; // Number of sectors in a track

USHORT NumberOfheads; // Number of heads on the disk

ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)

ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume

UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)

UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.

UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.

ULONG VolumeSerialNumber; // Volume serial number

CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory

CHAR FileSystemType[8]; // One of the strings "FAT12 ","FAT16 ",or "FAT "

UCHAR BootCodeAndData[448]; // The remainder of the boot sector

USHORT BootSectorMagic; // 0xAA55

} FAT_BOOTSECTOR,*PFAT_BOOTSECTOR;*/

OEMName db 'FrLdr1.0'

BytesPerSector dw 512

SectsPerCluster db 0

ReservedSectors dw 32

….

main:

;初始化

xor ax,ax ; Setup segment registers

mov ds,ax ; Make DS correct

mov es,ax ; Make ES correct

mov ss,ax ;Make SS correct

mov bp,7c00h

mov sp,7c00h ; Setup a stack

cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it

jne CheckSectorsPerFat

mov [BYTE bp+BootDrive],dl ; Save the boot drive

;下面检查参数是否正确

CheckSectorsPerFat:

cmp WORD [BYTE bp+SectorsPerFat],byte 0x00 ; Check the old 16-bit value of SectorsPerFat

jnz CheckFailed ; If it is non-zero then exit with an error

CheckTotalSectors: ; Check the old 16-bit value of TotalSectors & MaxRootEntries

cmp DWORD [BYTE bp+MaxRootEntries],byte 0x00; by comparing the DWORD at offset MaxRootEntries to zero

jnz CheckFailed ; If it is non-zero then exit with an error

CheckFileSystemVersion:

cmp WORD [BYTE bp+Fsversion],byte 0x00 ; Check the file system version word

jna GetDriveParameters ; It is zero,so continue

CheckFailed:

jmp PrintFileSystemError ; If it is not zero then exit with an error

;下面的函数名称都说明了他的作用

GetDriveParameters:

….省略

CalcDriveSize:

省略

;计算出来放在BiosCHSDriveSize里面

LoadExtraBootCode:

; First we have to load our extra boot code at

; sector 14 into memory at [0000:7e00h]

call ReadSectors

jmp StartSearch

;==========================================================

; Reads logical sectors into [ES:BX]

; EAX has logical sector number to read

; CX has number of sectors to read

ReadSectors:

;这里进行的工作是检查是否为LBA模式如果是进行LBA模式读取

; End of bootsector

;

; Now starts the extra boot code that we will store

; at sector 14 on a fat32 volume

;

; To remain multi-boot compatible with other operating

; systems we must not overwrite anything other than

; the bootsector which means we will have to use

; a different sector like 14 to store our extra boot code

;========================================================

;下面的代码是进行查找freeldr.sys,然后进行加载,加载到0000:8000

StartSearch:

; Now we must get the first cluster of the root directory

mov eax,DWORD [BYTE bp+RootDirstartCluster]

cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain

jb ContinueSearch ; If not continue,if so then we didn't find freeldr.sys

jmp PrintFileNotFound

ContinueSearch:

mov bx,2000h

mov es,bx ; Read cluster to [2000:0000h]

call ReadCluster ; Read the cluster

; Now we have to find our way through the root directory to

; The osloADER.SYS file

xor bx,bx

mov bl,[BYTE bp+SectsPerCluster]

shl bx,4 ; BX = BX * 512 / 32

mov ax,2000h ; We loaded at 2000:0000

mov es,ax

xor di,di

mov si,filename

mov cx,11

rep cmpsb ; Compare filenames

jz FoundFile ; If same we found it

dec bx

jnz FindFile

jmp PrintFileNotFound

FindFile:

mov ax,es ; We didn't find it in the prevIoUs dir entry

add ax,2 ; So lets move to the next one

mov es,ax ; And search again

xor di,filename

mov cx,11

rep cmpsb ; Compare filenames

jz FoundFile ; If same we found it

dec bx ; Keep searching till we run out of dir entries

jnz FindFile ; Last entry?

; Get the next root dir cluster and try again until we run out of clusters

mov eax,DWORD [BYTE bp+RootDirstartCluster]

call GetFatEntry

mov [BYTE bp+RootDirstartCluster],eax

jmp StartSearch

FoundFile:

; display "Loading FreeLoader..." message

mov si,msgLoading ; Loading message

call PutChars ; display it

xor di,di ; ES:DI has dir entry

xor dx,dx

mov ax,WORD [es:di+14h] ; Get start cluster high word

shl eax,16

mov ax,WORD [es:di+1ah] ; Get start cluster low word

CheckStartCluster:

cmp eax,2 ; Check and see if the start cluster starts at cluster 2 or above

jnb CheckEndCluster ; If so then continue

jmp PrintFileSystemError ; If not exit with error

CheckEndCluster:

cmp eax,0ffffff8h ; Check and see if the start cluster is and end of cluster chain indicator

jb InitializeLoadSegment ; If not then continue

jmp PrintFileSystemError ; If so exit with error

InitializeLoadSegment:

mov bx,800h

mov es,bx

LoadFile:

cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain

jae LoadFileDone ; If so continue,if not then read the next one

push eax

xor bx,bx ; Load ROSLDR starting at 0000:8000h

push es

call ReadCluster

pop es

xor bx,5 ; BX = BX * 512 / 16

mov ax,es ; Increment the load address by

add ax,bx ; The size of a cluster

mov es,ax

pop eax

push es

call GetFatEntry ; Get the next entry

pop es

jmp LoadFile ; Load the next cluster (if any)

LoadFileDone:

mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL

mov dh,[BootPartition] ; Load boot partition into DH

;看这里是把freeldr加载到0000:8000位置然后跳转到此处

xor ax,ax

push ax ; We loaded at 0000:8000

push WORD 8000h ; We will do a far return to 0000:8000h

retf ; Transfer control to ROSLDR

;下面是fat格式磁盘的解析函数,可以玩下

; Returns the FAT entry for a given cluster number

; On entry EAX has cluster number

; On return EAX has FAT entry for that cluster

GetFatEntry:

shl eax,2 ; EAX = EAX * 4 (since fat32 entries are 4 bytes)

mov ecx,eax ; Save this for later in ECX

xor edx,edx

movzx ebx,WORD [BYTE bp+BytesPerSector]

push ebx

div ebx ; FAT Sector Number = EAX / BytesPerSector

movzx ebx,WORD [BYTE bp+ReservedSectors]

add eax,ebx ; FAT Sector Number += ReservedSectors

mov ebx,DWORD [BYTE bp+HiddenSectors]

add eax,ebx ; FAT Sector Number += HiddenSectors

pop ebx

dec ebx

and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector

; EAX holds logical FAT sector number

; ECX holds FAT entry offset

; Now we have to check the extended flags

; to see which FAT is the active one

; and use it,or if they are mirrored then

; no worries

movzx ebx,WORD [BYTE bp+ExtendedFlags] ; Get extended flags and put into ebx

and bx,0x0f ; Mask off upper 8 bits,Now we have active fat in bl

jz LoadFatSector ; If fat is mirrored then skip fat calcs

cmp bl,[BYTE bp+NumberOfFats] ; Compare bl to number of fats

jb GetActiveFatOffset

jmp PrintFileSystemError ; If bl is bigger than numfats exit with error

GetActiveFatOffset:

push eax ; Save logical FAT sector number

mov eax,[BYTE bp+SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax

mul ebx ; Multiplied by the active FAT index we have in ebx

pop edx ; Get logical FAT sector number

add eax,edx ; Add the current FAT sector offset

LoadFatSector:

push ecx

; EAX holds logical FAT sector number

; Check if we have already loaded it

cmp eax,DWORD [FatSectorInCache]

je LoadFatSectorAlreadyLoaded

mov DWORD [FatSectorInCache],eax

mov bx,7000h

mov es,bx

xor bx,bx ; We will load it to [7000:0000h]

mov cx,1

call ReadSectors

LoadFatSectorAlreadyLoaded:

mov bx,bx

pop ecx

mov eax,DWORD [es:ecx] ; Get FAT entry

and eax,0fffffffh ; Mask off reserved bits

ret

FatSectorInCache: ; This variable tells us which sector we currently have in memory

dd 0ffffffffh ; There is no need to re-read the same sector if we don't have to

; Reads cluster number in EAX into [ES:0000]

ReadCluster:

; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;

….

; displays a file not found error message

; And reboots

PrintFileNotFound:

mov si,msgFreeLdr ; FreeLdr not found message

call PutChars ; display it

mov si,msgAnyKey ; Press any key message

call PutChars ; display it

jmp Reboot

msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0

filename db 'FREELDR SYS'

msgLoading db 'Loading FreeLoader...',0

times 1022-($-$$) db 0 ; Pad to 1022 bytes

dw 0aa55h ; BootSector signature

,看完代码也有单晕晕乎乎了,我们来总结下fat32.asm。首先加载到0000:7c00,接下来就是那个结构体,而上面跳转到main函数那了.开始当然是对一些寄存器的初始化,接着就是检查BootSector的参数是否正确,接着计算整个磁盘的存储量,为什么要计算这个呢?为了检查磁盘是否支持LBA模式。再下面的工作就是查找freeldr.sys.并将其加载到内存0000:8000,

其中又有fat文件格式的操作….

需要的知识点:

1,汇编是必要的.

2,bootsector.

3,fat32文件系统解析

4,怎么检查是否支持LBA模式

5,int 10,int 13 貌似都会吧..

6,得会使用nasm编译呀!!

对了freeldr目录下有个note.txt里面有内存分配表如下,大家好好看看:

Memory layout:

0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data

0000:1000 - 0000:6FFF: Real mode stack area

0000:7000 - 0000:7FFF: Cmdline (multiboot)

0000:8000 - xxxx:xxxx: FreeLoader program & data area

xxxx:xxxx - 7000:7FFF: Random memory allocation heap

7000:8000 - 7000:FFFF: Protected mode stack area

8000:0000 - 8000:FFFF: File system read buffer

9000:0000 - 9000:FFFF: disk read buffer for BIOS Int 13h

A000:0000 - FFFF:FFFF: reserved

.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的实例源码等更多相关知识的信息可以在本站进行查询。

本文标签: